正确使用 DrawRect 覆盖 - 我可以防止视图拉伸吗?
Posted
技术标签:
【中文标题】正确使用 DrawRect 覆盖 - 我可以防止视图拉伸吗?【英文标题】:Proper use of DrawRect override - can I prevent view stretching? 【发布时间】:2013-04-01 20:30:11 【问题描述】:编辑:以下详细问题的简化版本:您能否通过子类 drawRect 更新 UIView 的边界而不导致视图内容拉伸?
我正在构建一个新闻阅读器应用程序,并且一直在研究如何将我的 UIView 拆分为列并仍然对内容进行分页。我相信我已经对列进行了基本编码(将 XML 节点内容按段落拆分为数组,然后通过检测不切断段落所需的总面积进行解析。)
我遇到的问题是我无法在没有文本拉伸的情况下更新 ContentBounds,即使里面的内容足够大以支持未拉伸的视图。
基本上是这样的:
contentBounds = CGSizeMake(self.bounds.size.width, self.bounds.size.height+COLUMN_YPOS);
[renderer updateContentBounds:contentBounds];
造成这种情况:(图片下方的完整代码)
- (void)drawRect:(CGRect)rect
NSString *string = contentString;
[string stringByReplacingOccurrencesOfString:@"<br>" withString:@"\n\n"];
// column width
int COLUMN_WIDTH = self.bounds.size.width/2-40;
int COLUMN_HEIGHT = self.bounds.size.height-100;
int COLUMN_XPOS = 20;
int COLUMN_YPOS = 0;
int PAGE_HEIGHT = COLUMN_HEIGHT + 40;
CGSize maximumSize = CGSizeMake(COLUMN_WIDTH, COLUMN_HEIGHT-20);
NSArray *paragraphs = [string componentsSeparatedByString:@"\n"];
NSString *textBuffer = @"";
NSString *preBuffer = @"";
NSString *currentStringSegment;
for (int i=0; i<[paragraphs count]; i++)
currentStringSegment = [paragraphs objectAtIndex:i];
preBuffer = textBuffer;
textBuffer = [textBuffer stringByAppendingString:@"\n\n"];
textBuffer = [textBuffer stringByAppendingString:currentStringSegment];
CGSize expectedSize = [textBuffer sizeWithFont:[UIFont fontWithName:@"Times New Roman" size:16] constrainedToSize:CGSizeMake(COLUMN_WIDTH, COLUMN_HEIGHT) lineBreakMode:NSLineBreakByWordWrapping];
if(expectedSize.height > maximumSize.height)
[preBuffer drawInRect:CGRectMake(COLUMN_XPOS, COLUMN_YPOS, COLUMN_WIDTH, COLUMN_HEIGHT) withFont:[UIFont fontWithName:@"Times New Roman" size:16] lineBreakMode:NSLineBreakByWordWrapping alignment:NSTextAlignmentLeft];
i--;
textBuffer = @"";
preBuffer = @"";
if(COLUMN_XPOS > 20)
COLUMN_XPOS = 20;
COLUMN_YPOS += PAGE_HEIGHT;
else
COLUMN_XPOS = COLUMN_WIDTH + 60;
if(![preBuffer isEqualToString:@""] && preBuffer != nil)
[preBuffer drawInRect:CGRectMake(COLUMN_XPOS, COLUMN_YPOS, COLUMN_WIDTH, COLUMN_HEIGHT) withFont:[UIFont fontWithName:@"Times New Roman" size:16] lineBreakMode:NSLineBreakByWordWrapping alignment:NSTextAlignmentLeft];
contentBounds = CGSizeMake(self.bounds.size.width, self.bounds.size.height);
[renderer updateContentBounds:contentBounds];
【问题讨论】:
您是否将 UIView 的内容模式设置为 UIViewContentModeScaleToFill 以外的模式?您确定不想使用标签或文本视图,甚至是 Web 视图吗?在 drawRect 中处理它意味着您正在创建一个位图,因此,您必须在渲染它之前自己完成所有工作,例如放置和缩放。 我曾讨论过使用 Web 视图,但我希望能够动态呈现按页面拆分列的页面。我可以从 drawRect 中调整视图的比例吗?还是我需要将新维度传递给另一个函数来处理? 我不得不问:为什么不直接使用 UILabel 作为分页视图的子视图来充当列?或者 UITextView 如果你想滚动?这似乎是很多不必要的努力。 【参考方案1】:当边界更改由contentMode
属性确定时UIView
的行为。
如果您查看documentation,您将阅读:
contentMode
属性中的值决定了位图是否应该缩放以适应新的边界,或者只是固定到视图的一个角或边缘。
默认情况下,contentMode
设置为 UIViewContentModeScaleToFill
,您可以在同一个文档页面中阅读,
使视图的内容被缩放以适应新的帧大小。
您可能希望将视图的contentMode
更改为不失真的行为,例如UIViewContentModeTop
,这将使在视图边界顶部对齐的内容居中。
您可以找到contentMode
here 的所有可能值。
【讨论】:
具体来说,如果您希望系统在更改视图的边界时发送drawRect:
,请将contentMode
设置为UIViewContentModeRedraw
。【参考方案2】:
您可以在分页模式下使用 UIScrollView。
Scrolling Using Paging Mode
您可以在 UIScrollView 中放置一个 UIWebView 并使用 html/CSS 创建列,关闭 Web 视图上的用户交互,并使用 UIScrollView 水平滚动列。
【讨论】:
以上是关于正确使用 DrawRect 覆盖 - 我可以防止视图拉伸吗?的主要内容,如果未能解决你的问题,请参考以下文章
子类化 UIToolbar 并覆盖 drawRect: - UIBarButtonItems 不显示