iOS7 UITextView contentsize.height替代


78

我正在将一个应用程序从iOS 6.1移植到iOS7。我正在使用一种布局,该布局的UITextView宽度固定,但是高度取决于其contentsize。对于iOS 6.1,检查contentsize.height并将其设置为textview的框架高度就足够了,但是在iOS 7上不起作用。

然后,如何UITextView根据显示的文字创建具有固定宽度但动态高度的?

注意:我是通过代码而不是使用Interface Builder创建这些视图的。

Answers:


180

使用以下代码,您可以根据固定宽度更改UITextView的高度(在iOS 7和早期版本上有效):

- (CGFloat)textViewHeightForAttributedText:(NSAttributedString *)text andWidth:(CGFloat)width
{
    UITextView *textView = [[UITextView alloc] init];
    [textView setAttributedText:text];
    CGSize size = [textView sizeThatFits:CGSizeMake(width, FLT_MAX)];
    return size.height;
}

使用此功能,您将获得NSAttributedString和固定宽度以返回所需的高度。

如果要从具有特定字体的文本中计算框架,则需要使用以下代码:

- (CGSize)text:(NSString *)text sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size
{
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
    {
        CGRect frame = [text boundingRectWithSize:size
                                          options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
                                       attributes:@{NSFontAttributeName:font}
                                          context:nil];
        return frame.size;
    }
    else
    {
        return [text sizeWithFont:font constrainedToSize:size];
    }
}

您可以将其添加到SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO项目中的prefix.pch文件中,如下所示:

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

您还可以通过以下方式替换之前的测试SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)

if ([text respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)])‌

我只能在24小时后给您。请耐心等待,这是您的:)
Zoltan Varadi

16
也许您应该链接到您从中得到的答案?stackoverflow.com/questions/18368567/...
安德鲁-考菲尔德

@Jordan Montel,还有一个问题,如果我的宽度和高度固定,如何为分配的字符串找到最佳字体大小?我在iOS7上也有类似的问题(在iOS6上我可以做到)
LiangWang

1
@Jacky:反复试验;将大小增加或减少1,直到计算出的高度过大为止。或将其设置为1000,然后自动调整大小以适合。
2013年

这个答案已经不正确了。尝试在此类文本字段中输入很多文本。大小突然错误?至少NSStringDrawingUsesFontLeading是多余的
user2159978 2014年

42

这对我适用于iOS6和7:

CGSize textViewSize = [self.myTextView sizeThatFits:CGSizeMake(self.myTextView.frame.size.width, FLT_MAX)];
    self.myTextView.height = textViewSize.height;

嗨,是的,这对我来说很正常……我用的是“ txtviewHeight.frame.size.height”,而不是“ txtviewHeight.contentSize.height”
玛尼

为什么我在“ UITextView”类型的对象上找不到属性高度?
Hexark

@HexarktextView.bounds.size.height
用户

21

在iOS7中,UITextView用于NSLayoutManager布局文本:

// If YES, then the layout manager may perform glyph generation and layout for a given portion of the text, without having glyphs or layout for preceding portions.  The default is NO.  Turning this setting on will significantly alter which portions of the text will have glyph generation or layout performed when a given generation-causing method is invoked.  It also gives significant performance benefits, especially for large documents.
@property(NS_NONATOMIC_IOSONLY) BOOL allowsNonContiguousLayout;

禁用allowsNonContiguousLayout修复contentSize

textView.layoutManager.allowsNonContiguousLayout = NO;

7
您的答案不适合这个问题,但适合我的问题。所以我投了赞成票:)
越南

这并不适合我。滚动被禁用。
Dvole

这段代码解决了我的问题,但是,导致生成的方法对您的注释意味着什么?
Code Farmer

15

使用这个小功能

-(CGSize) getContentSize:(UITextView*) myTextView{
    return [myTextView sizeThatFits:CGSizeMake(myTextView.frame.size.width, FLT_MAX)];
}

适用于iOS6和iOS7。谢谢!
Paul Brady 2013年

4

我的最终解决方案基于HotJard,但同时包含文本容器的顶部和底部插图,而不是使用2 * fabs(textView.contentInset.top):

- (CGFloat)textViewHeight:(UITextView *)textView
{
    return ceilf([textView.layoutManager usedRectForTextContainer:textView.textContainer].size.height +
                 textView.textContainerInset.top +
                 textView.textContainerInset.bottom);
}

3

有更简单的解决方案,使用此方法:

+(void)adjustTextViewHeightToContent:(UITextView *)textView;
{
    if([[UIDevice currentDevice].systemVersion floatValue] >= 7.0f){
        textView.height = [textView.layoutManager usedRectForTextContainer:textView.textContainer].size.height+2*fabs(textView.contentInset.top);
    }else{
        textView.height = textView.contentSize.height;
    }
}

UPD:仅用于显示文本(isEditable = NO)


看来您的孤单无效。当textview goto第二行usedRectForTextContainer方法返回相同的高度时。
Valerii Pavlov

哦,可能是,我只是用它来显示文本
HotJard

1
   _textView.textContainerInset = UIEdgeInsetsZero;
   _textView.textContainer.lineFragmentPadding = 0;

只是不要忘记lineFragmentPadding


0

简单的解决方案-textView.isScrollEnabled = false 在另一个滚动视图或带有UITableViewAutomaticDimension


0

@安娜的,@Blake汉密尔顿在溶液中迅速

var contentHeight: CGFloat = textView.sizeThatFits(textView.frame.size).height

对我来说,好的是contentSize,当isScrollEnable设置为false时,它还返回正确的。设置为false将返回文本视图的框架大小,而不是内容大小。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.