78

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

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

注意:我是从代码中创建这些视图,而不是使用 Interface Builder。

4

9 回答 9

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:)])‌
于 2013-09-28T13:25:07.343 回答
42

这适用于 iOS6 和 7:

CGSize textViewSize = [self.myTextView sizeThatFits:CGSizeMake(self.myTextView.frame.size.width, FLT_MAX)];
    self.myTextView.height = textViewSize.height;
于 2013-10-09T13:19:29.350 回答
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;
于 2014-02-27T11:02:21.243 回答
15

使用这个小功能

-(CGSize) getContentSize:(UITextView*) myTextView{
    return [myTextView sizeThatFits:CGSizeMake(myTextView.frame.size.width, FLT_MAX)];
}
于 2013-10-13T00:37:55.260 回答
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);
}
于 2013-10-07T10:01:35.510 回答
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)

于 2013-10-02T13:00:10.440 回答
1
   _textView.textContainerInset = UIEdgeInsetsZero;
   _textView.textContainer.lineFragmentPadding = 0;

只是不要忘记 lineFragmentPadding

于 2016-08-08T03:25:54.840 回答
0

简单的解决方案 -textView.isScrollEnabled = false 在另一个滚动视图或 tableView 单元格中时完美工作UITableViewAutomaticDimension

于 2017-11-28T10:37:54.267 回答
0

@Ana's,@Blake Hamilton 在swift中的解决方案。

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

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

于 2018-09-16T09:40:34.267 回答