是否有一个好的方法来调整UITextView的大小以符合其内容?例如,我有一个包含一行文本的UITextView:

"Hello world"

然后我添加了另一行文本:

"Goodbye world"

在Cocoa Touch中是否有一个好的方法来获取矩形来保存文本视图中的所有行,这样我就可以相应地调整父视图?

另一个例子是,查看Calendar应用程序中用于事件的notes字段——注意单元格(以及它包含的UITextView)如何展开以保存notes字符串中的所有文本行。


当前回答

这在ios7或更高版本上不再适用

实际上有一个非常简单的方法来调整UITextView的大小,使其达到内容的正确高度。它可以使用uitextviewcontentsize来完成。

CGRect frame = _textView.frame;
frame.size.height = _textView.contentSize.height;
_textView.frame = frame;

需要注意的一件事是,只有在使用addSubview将UITextView添加到视图之后,正确的contentSize才可用。在此之前,它等于frame。size

如果开启自动布局,这将不起作用。对于自动布局,一般的方法是使用sizeThatFits方法并在高度约束上更新常量值。

CGSize sizeThatShouldFitTheContent = [_textView sizeThatFits:_textView.frame.size];
heightConstraint.constant = sizeThatShouldFitTheContent.height;

hightconstraint是一个布局约束,通常通过IBOutlet将属性链接到故事板中创建的高度约束来设置。


再加上这个惊人的答案,2014年,如果你:

[self.textView sizeToFit];

只有iPhone6+有不同的表现:

只有6+(不是5s或6),它确实添加了“一个更多的空白行”到UITextView。“RL解决方案”完美地解决了这个问题:

CGRect _f = self.mainPostText.frame;
_f.size.height = self.mainPostText.contentSize.height;
self.mainPostText.frame = _f;

它修复了6+上的“额外行”问题。

其他回答

我会在页面底部发布正确的解决方案,以防有人勇敢(或绝望)读到这一点。

这里是那些gitHub回购,谁不想读所有的文本:resizableTextView

这适用于iOs7(我相信它将适用于iOs8)和自动布局。你不需要魔法数字,禁用布局之类的东西。简洁优雅的解决方案。

我认为,所有约束相关的代码都应该去updateConstraints方法。让我们创建自己的ResizableTextView。

我们在这里遇到的第一个问题是在viewDidLoad方法之前不知道真实的内容大小。我们可以根据字体大小、换行等进行计算。但我们需要稳健的解决方案,所以我们会:

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

现在我们知道真实的contentSize,不管我们在哪里:在viewDidLoad之前还是之后。现在在textView上添加高度约束(通过storyboard或代码,无论如何)。我们用contentSize.height来调整这个值:

[self.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *constraint, NSUInteger idx, BOOL *stop) {
    if (constraint.firstAttribute == NSLayoutAttributeHeight) {
        constraint.constant = contentSize.height;
        *stop = YES;
    }
}];

最后要做的事情是告诉超类updateConstraints。

[super updateConstraints];

现在我们的类看起来是这样的:

ResizableTextView.m

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

    [self.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *constraint, NSUInteger idx, BOOL *stop) {
        if (constraint.firstAttribute == NSLayoutAttributeHeight) {
            constraint.constant = contentSize.height;
            *stop = YES;
        }
    }];

    [super updateConstraints];
}

又漂亮又干净,对吧?你不需要在控制器中处理这些代码!

但是等等! 没有动画!

你可以很容易地动画变化,使textView伸展顺利。这里有一个例子:

    [self.view layoutIfNeeded];
    // do your own text change here.
    self.infoTextView.text = [NSString stringWithFormat:@"%@, %@", self.infoTextView.text, self.infoTextView.text];
    [self.infoTextView setNeedsUpdateConstraints];
    [self.infoTextView updateConstraintsIfNeeded];
    [UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionLayoutSubviews animations:^{
        [self.view layoutIfNeeded];
    } completion:nil];

另一个方法是使用NSString方法查找特定字符串将占用的大小:

-(CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)大小

它返回符合给定字符串和给定字体的矩形的大小。传入一个具有所需宽度和最大高度的大小,然后您可以查看返回的适合文本的高度。还有一个版本允许您指定换行模式。

然后,您可以使用返回的大小来更改视图的大小以适应。

非常容易工作的解决方案使用代码和故事板。

通过代码

textView.scrollEnabled = false

通过故事板

取消选中“滚动启用”

除此之外什么都不用做。

这工作得很好,当我需要使文本在一个UITextView适合一个特定的区域:

// The text must already be added to the subview, or contentviewsize will be wrong.

- (void) reduceFontToFit: (UITextView *)tv {
    UIFont *font = tv.font;
    double pointSize = font.pointSize;

    while (tv.contentSize.height > tv.frame.size.height && pointSize > 7.0) {
        pointSize -= 1.0;
        UIFont *newFont = [UIFont fontWithName:font.fontName size:pointSize];
        tv.font = newFont;
    }
    if (pointSize != font.pointSize)
        NSLog(@"font down to %.1f from %.1f", pointSize, tv.font.pointSize);
}

我们可以用约束来做。

为UITextView设置高度约束。

2.为高度限制创建IBOutlet。

 @property (weak, nonatomic) IBOutlet NSLayoutConstraint *txtheightconstraints;

3.不要忘记为你的textview设置委托。

4.

-(void)textViewDidChange:(UITextView *)textView
{
    CGFloat fixedWidth = textView.frame.size.width;
    CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
    CGRect newFrame = textView.frame;
    newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
    NSLog(@"this is updating height%@",NSStringFromCGSize(newFrame.size));
    [UIView animateWithDuration:0.2 animations:^{
                  _txtheightconstraints.constant=newFrame.size.height;
    }];

}

然后像这样更新你的约束: