如果要包装的文本中有一个长字符串,sizeWithFont不会为UITextView提供正确的高度

时间:2010-02-25 01:23:33

标签: iphone objective-c nsstring uitextfield

有没有办法使用以下方法获得正确的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;
}

6 个答案:

答案 0 :(得分:21)

UITextViewUILabel中包含的UIScrollView不完全相同。它的行间距与sizeWithFont:constrainedToSize:linkBreakMode:未考虑的字体大小和边距不同。

了解字体大小后,您可以计算行数并考虑行间距。您可以猜测边距并尝试欺骗sizeWithFont:以提供更有用的答案。

流行的解决方案似乎是:

  • 如果您不需要任何UILabel功能,只需使用UITextView

  • 如果您需要hyperlinks,则覆盖UIButtons看起来像UILabel上的超链接

  • 使用屏幕外UITextView及其sizeToFit方法获得真实答案

我没有第三个选项的运气,但听起来它应该有用,所以也许我做错了。

我将尝试使用UILabel并覆盖超链接按钮。我们会看到结果如何。

如果失败了,Loren Brichter(Tweetie成名)总是选择:使用UIView将所有内容都自己绘制成CoreGraphics

祝你好运!

答案 1 :(得分:9)

查看此帖子How do I size a UITextView to its content?

看起来像textView.contentSize.height应该有效(需要注意的是,只有在使用addSubview将UITextView添加到视图后才能使用正确的contentSize)

答案 2 :(得分:1)

你说你的UITableView有不同的高度。您是否为所有单元格设置了重用标识符?可能是已经设置了高度的旧电池正在重复使用。如果这是问题,则应在重复使用时再次调整单元格的大小。

答案 3 :(得分:1)

到目前为止,我找到的最佳解决方案是使用相同的字体设置单独隐藏UITextView,并设置其文本。之后,它的contetSize应该是准确的。

答案 4 :(得分:1)

您使用的宽度是UITextView的宽度...但是您不关心该宽度,而是关注嵌套在文本视图中的实际文本区域的宽度。

默认情况下,UITextViews在其边框周围有填充,以便在键入的文本和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));

答案 5 :(得分:0)

受@ 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) )。