如果要换行的文本中有长字符串,则 sizeWithFont 不会为 UITextView 提供正确的高度
Posted
技术标签:
【中文标题】如果要换行的文本中有长字符串,则 sizeWithFont 不会为 UITextView 提供正确的高度【英文标题】:sizeWithFont doesn't give correct height for UITextView if there is a long string in the text being wrapped 【发布时间】:2010-02-25 01:23:32 【问题描述】:有没有办法获得正确大小的 NSString 使用:
- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode
不会被 2 或 300 个字符串抛弃。目前,如果我尝试在这些长字符串上使用此方法,则会错误地计算它们,最终在 UITextView 的底部会出现大量空白。
我尝试过使用 UILineBreakModeWordWrap 和 UILineBreakModeCharacterWrap。
正在调整大小
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
CGFloat result = 44.0f;
NSString* text = nil;
CGFloat width = 0;
CGFloat tableViewWidth;
CGRect bounds = [UIScreen mainScreen].bounds;
tableViewWidth = bounds.size.width;
width = tableViewWidth - 150;
text = stringWithLongWords;
if (text)
CGSize textSize = width, 20000.0f ;
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:10.0f] constrainedToSize:textSize lineBreakMode:UILineBreakModeWordWrap];
size.height += 50.0f;
result = MAX(size.height, 44.0f+30.0f);
return result;
【问题讨论】:
你到底想做什么?我认为 sizeWithFont: 效果很好,也许这就是您将这些信息应用于 UITextView 的方式。请解释一下。 我有一个自定义 UITableView 单元格,其中有 2 个 UILabel 和一个 UITextView,使用 sizeWithFont 来计算单元格高度所需的大小,有时单元格最终会超过 400 像素。 【参考方案1】:UITextView
与包裹在UIScrollView
中的UILabel
不完全相同。它的行距不同于sizeWithFont:constrainedToSize:linkBreakMode:
不考虑的字体大小和边距。
了解您的字体大小后,您或许可以计算行数并考虑行距。你可以在空白处猜测并尝试欺骗sizeWithFont:
以给出更有用的答案。
流行的解决方案似乎是:
如果您不需要任何 UITextView
功能,只需使用 UILabel
如果您需要hyperlinks
,请将看起来像超链接的UIButtons
覆盖在UILabel
上
使用屏幕外的UITextView
及其sizeToFit
方法来获得真正的答案
我对第 3 个选项没有运气,但听起来它应该可以工作,所以也许我做错了什么。
我将尝试使用UILabel
和覆盖超链接的按钮。我们会看看结果如何。
如果失败,Loren Brichter(Tweetie 成名)总是有一个选择:使用CoreGraphics
将所有内容绘制到UIView
中。
祝你好运!
【讨论】:
第三个选项可能不起作用,因为 sizeToFit 在 UITextView 呈现到屏幕之前不起作用。只是一个想法。 有趣。我想知道您是否可以在屏幕上渲染它,但使用 alpha = 0 或非常低的值来欺骗它进行渲染,但人眼仍然看不到。 这可能会奏效,而且会是一个有趣的实验。不过,我很想找到一种在渲染之前正确计算高度的方法。在 UITableViewCells 中使用 UITextViews 时会非常有用。 第三个选项只在 ios6 中对我有用。看起来与 ***.com/questions/18859637/… 相关的东西相当于 sizeWithFont: 在这里讨论:***.com/questions/18903304/… 这里的实际解决方案(以及问题的原因):***.com/a/27322396/2057171【参考方案2】:查看这篇帖子How do I size a UITextView to its content?
看起来 textView.contentSize.height 应该可以工作(需要注意的是正确的 contentSize 只有在 UITextView 使用 addSubview 添加到视图后才可用)
【讨论】:
【参考方案3】:你说你有一个不同高度的UITableView
。您是否将所有单元格的重用标识符设置为相同的值?可能是已经设置了高度的旧单元正在被重复使用。如果这是问题所在,您应该在重新使用单元格时再次调整其大小。
【讨论】:
UITableView 上只有一个这种类型的单元格,我检查了这是否是一个问题,但似乎不是。【参考方案4】:到目前为止,我发现的最佳解决方案是使用相同的字体设置单独隐藏 UITextView,并设置其文本。之后,它的 contetSize 应该是准确的。
【讨论】:
【参考方案5】:您使用的宽度是 UITextView 的宽度...但您并不关心该宽度,您关心的是嵌套在文本视图中的实际文本区域的宽度。
默认情况下,UITextView 的边框周围有填充,以在键入的文本和 UITextView 的边缘之间产生几个像素宽(顶部长)的空间...要获得正确的大小,您应该不要使用
textView.frame.size.width
而是,
textView.frame.size.width-(textView.contentInset.left+textView.contentInset.right+textView.textContainerInset.left+textView.textContainerInset.right+textView.textContainer.lineFragmentPadding/*left*/+textView.textContainer.lineFragmentPadding/*right*/)
^它采用 UITextView 的宽度并减去所有填充,因此您只剩下可输入文本区域的宽度。
除了lineFragmentPadding
没有底部之外,高度也是如此,因此您只需将其减去一次而不是两次。
最后的代码是这样的:
CGSize textViewContentSize = CGSizeMake(theTextView.frame.size.width-(theTextView.contentInset.left+theTextView.contentInset.right+theTextView.textContainerInset.left+theTextView.textContainerInset.right+theTextView.textContainer.lineFragmentPadding/*left*/+theTextView.textContainer.lineFragmentPadding/*right*/), theTextView.frame.size.height-(theTextView.contentInset.top+theTextView.contentInset.bottom+theTextView.textContainerInset.top+theTextView.textContainerInset.bottom+theTextView.textContainer.lineFragmentPadding/*top*//*+theTextView.textContainer.lineFragmentPadding*//*there is no bottom padding*/));
CGSize calculatedSize = [theTextView.text sizeWithFont:theTextView.font
constrainedToSize:textViewContentSize
lineBreakMode:NSLineBreakByWordWrapping];
CGSize adjustedSize = CGSizeMake(ceilf(calculatedSize.width), ceilf(calculatedSize.height));
【讨论】:
【参考方案6】:受@MrNickBarker 的回答启发,这是我的解决方案:
CGFloat width = 280.0f;
UITextView *t = [[UITextView alloc] init];
[t setFont:[UIFont systemFontOfSize:17]];
[label setText:@"some short or long text, works both"];
CGRect frame = CGRectMake(0, 0, width, 0);
[t setFrame:frame];
// Here's the trick: after applying the 0-frame, the content size is calculated and can be used in a second invocation
frame = CGRectMake(0, 0, width, t.contentSize.height);
[t setFrame:frame];
留给我的唯一问题是这不适用于修改后的插图。
仍然无法相信需要这样的扭曲,但由于-[NSString sizeWithFont:forWidth:lineBreakMode:]
不尊重插入、填充、边距、行间距等,看来这是目前唯一可行的解决方案(即 iOS 6)。
【讨论】:
以上是关于如果要换行的文本中有长字符串,则 sizeWithFont 不会为 UITextView 提供正确的高度的主要内容,如果未能解决你的问题,请参考以下文章