如何在iOS 7上调整UITextView的内容?

Hen*_*son 64 height dynamic uitextview ios7

多年来我一直在使用这里接受的答案.

在iOS 7上,无论文本内容如何,​​contentSize.height都将成为frame.height-8.

在iOS 7上调整高度的工作方法是什么?

Hen*_*son 55

我喜欢这个最小的代码更改:刚过添加这两条线addSubview,并抓住面前heightframe

...
[scrollView1 addSubview: myTextView];

    [myTextView sizeToFit]; //added
    [myTextView layoutIfNeeded]; //added

CGRect frame = myTextView.frame;
...
Run Code Online (Sandbox Code Playgroud)

这是向后兼容的iOS 6测试.请注意它收缩包装宽度.如果你只是对高度感兴趣并且有一个固定的宽度,只需抓住新的高度但设置原始宽度,它就像以前一样在iOS 6和7上工作.

(推测:它的大小也适合iOS 7,但布局会在以后更新或在单独的线程中更新,这会立即强制布局,以便及时更新其框架,以便稍后使用其高度值在同一个线程中.)

笔记:

1)您可能已经或可能没有实现外部容器以这种方式调整大小.它似乎确实是一个常见的片段,我在我的项目中使用过它.

2)由于sizeToFit似乎在iOS 7上按预期工作,您可能不需要过早的addSubView.它是否仍然可以在iOS 6上运行然后我没有经过测试.

3)推测:额外的layoutIfNeeded中间线程可能是昂贵的.我看到的替代方法是在布局回调上调整外部容器的大小(触发或不取决于操作系统是否需要布局),外部容器调整大小将导致另一个布局更新.两种更新都可能与其他布局更新相结合,以提高效率.如果你有这样的解决方案,你也可以说这更有效,其添加为答案,我一定会在这里提到它.


ma1*_*w28 33

由于我使用的自动布局,我用的值[textView sizeThatFits:CGSizeMake(textView.frame.size.width, CGFLOAT_MAX)].height更新constant了的textView的高度UILayoutConstraint.


tar*_*mes 17

我使用了一个改编版本的madmik的答案,消除了软糖因素:

- (CGFloat)measureHeightOfUITextView:(UITextView *)textView
{
    if ([textView respondsToSelector:@selector(snapshotViewAfterScreenUpdates:)])
    {
        // This is the code for iOS 7. contentSize no longer returns the correct value, so
        // we have to calculate it.
        //
        // This is partly borrowed from HPGrowingTextView, but I've replaced the
        // magic fudge factors with the calculated values (having worked out where
        // they came from)

        CGRect frame = textView.bounds;

        // Take account of the padding added around the text.

        UIEdgeInsets textContainerInsets = textView.textContainerInset;
        UIEdgeInsets contentInsets = textView.contentInset;

        CGFloat leftRightPadding = textContainerInsets.left + textContainerInsets.right + textView.textContainer.lineFragmentPadding * 2 + contentInsets.left + contentInsets.right;
        CGFloat topBottomPadding = textContainerInsets.top + textContainerInsets.bottom + contentInsets.top + contentInsets.bottom;

        frame.size.width -= leftRightPadding;
        frame.size.height -= topBottomPadding;

        NSString *textToMeasure = textView.text;
        if ([textToMeasure hasSuffix:@"\n"])
        {
            textToMeasure = [NSString stringWithFormat:@"%@-", textView.text];
        }

        // NSString class method: boundingRectWithSize:options:attributes:context is
        // available only on ios7.0 sdk.

        NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
        [paragraphStyle setLineBreakMode:NSLineBreakByWordWrapping];

        NSDictionary *attributes = @{ NSFontAttributeName: textView.font, NSParagraphStyleAttributeName : paragraphStyle };

        CGRect size = [textToMeasure boundingRectWithSize:CGSizeMake(CGRectGetWidth(frame), MAXFLOAT)
                                                  options:NSStringDrawingUsesLineFragmentOrigin
                                               attributes:attributes
                                                  context:nil];

        CGFloat measuredHeight = ceilf(CGRectGetHeight(size) + topBottomPadding);
        return measuredHeight;
    }
    else
    {
        return textView.contentSize.height;
    }
}
Run Code Online (Sandbox Code Playgroud)


MKa*_*st3 16

基于其他答案,我使它成功(在Swift中).这解决了换行符的问题.

textView.sizeToFit()
textView.layoutIfNeeded()
let height = textView.sizeThatFits(CGSizeMake(textView.frame.size.width, CGFloat.max)).height
textView.contentSize.height = height
Run Code Online (Sandbox Code Playgroud)

需要自动布局.


bil*_*tum 15

如果您正在使用自动布局,则可以创建一个简单的UITextView子类,自定义文本视图高度以适合内容:

@interface ContentHeightTextView : UITextView

@end

@interface ContentHeightTextView ()
@property (nonatomic, strong) NSLayoutConstraint *heightConstraint;
@end

@implementation ContentHeightTextView

- (void)layoutSubviews
{
    [super layoutSubviews];

    CGSize size = [self sizeThatFits:CGSizeMake(self.bounds.size.width, FLT_MAX)];

    if (!self.heightConstraint) {
        self.heightConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:0 multiplier:1.0f constant:size.height];
        [self addConstraint:self.heightConstraint];
    }

    self.heightConstraint.constant = size.height;

    [super layoutSubviews];
}

@end
Run Code Online (Sandbox Code Playgroud)

当然,文本视图的宽度和位置必须由程序中其他位置配置的其他约束来定义.

如果在IB中创建此自定义文本视图,请为文本视图指定高度约束以满足Xcode; 只需确保在IB中创建的高度约束仅仅是占位符(即,勾选"在构建时删除"的框).

在此输入图像描述

实现UITextView子类的另一种方法如下(此实现可能有资格作为最佳实践):

@interface ContentHeightTextView ()
@property (nonatomic, strong) NSLayoutConstraint *heightConstraint;
@end

@implementation ContentHeightTextView

- (void)layoutSubviews
{
    [super layoutSubviews];

    [self setNeedsUpdateConstraints];
}

- (void)updateConstraints
{
    CGSize size = [self sizeThatFits:CGSizeMake(self.bounds.size.width, FLT_MAX)];

    if (!self.heightConstraint) {
        self.heightConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:0 multiplier:1.0f constant:size.height];
        [self addConstraint:self.heightConstraint];
    }

    self.heightConstraint.constant = size.height;
    [super updateConstraints];
}

@end
Run Code Online (Sandbox Code Playgroud)