设置文本后,使用自动布局获取UITextView的动态高度

30

我有一个UITextView,使用界面生成器设置自动布局,但它不可滚动,文本可以根据需要动态增加或减少,但我想知道在设置文本后新的UITextView高度是多少,我正在尝试做到这一点:

NSLog(@"text before: %.2f",self.myText.frame.size.height);
[self.myText setText:self.string];
NSLog(@"text after: %.2f",self.myText.frame.size.height);

这是结果:

text before: 47.50
text after: 47.50

当我运行时,视图中的文本增加了,但大小保持不变。如何在设置文本后获取实际高度?


我遇到了一个问题,我的TextView无法根据文字大小自动增长,您能否分享一下您实现这个功能的步骤? - Gaurav Abbi
相关代码:TextViewHeightConstraint.constant = [TextView intrinsicContentSize].height。另外要记得取消滚动! - Fattie
这个问题已经在下面的链接中得到了回答: https://stackoverflow.com/a/56156621/6386213 - Bhagyesh
14个回答

96

您需要做的是:

  • 设置所有约束条件,除了 高度约束之外
  • textViewscrollEnabled属性设置为NO

最后一个步骤起到了关键作用。

您的文本视图将根据其文本值自动调整大小。


1
这对我不起作用:输入的文本是不可见的,输入几行后,它最终出现在底部! - Nicolas Miari
忘记它:添加 textView.setContentOffset(CGPoint.zero, animated: false) 就解决了。 - Nicolas Miari
这是答案。 - Daniel Wood

34

如果您想要完全使用自动布局:

在“尺寸检查器”中:

  1. 内容压缩阻力优先级(垂直)设置为1000。

  2. 降低UITextView的约束高度的优先级,只需将其设为小于1000即可。

输入图像描述

在“属性检查器”中:

  1. 取消选中滚动启用

它完美地工作,否则所有上述代码在我的情况下都无法工作。谢谢。 - Fredric Cliver
是的,这个方法完美地运作着。我在编码设计部分使用了这个想法。 - Abishek Thangaraj

13

4
这是一个仅包含链接的答案,请问您能否在回答中总结链接内容? - Flimm
1
这对我的消息设计起作用。但是我只需要在第四行之后增加四行。textView停止高度增加并滚动。如果有人知道,请回答或分享链接。 - Abishek Thangaraj

12

这个应该可以工作:

NSLog(@"text before: %.2f",self.myText.frame.size.height);
[self.myText setText:self.string];
[self.myText layoutIfNeeded]; // <--- Add this
NSLog(@"text after: %.2f",self.myText.frame.size.height);

这是我的 Github 上的一个示例实现:https://github.com/guillaume-algis/SO-27060338


刚刚测试过了,对我有效。我在我的Github上放了一个例子:https://github.com/guillaume-algis/SO-27060338 - Guillaume Algis

8

Swift 3.0

textView.isScrollEnabled = false

这样可以让AutoLayout发挥其作用。

2
这基本上是唯一需要的。我已经在Interface Builder中添加了textView,因此我必须在UITextView的identity inspector中取消选中“Scrolling Enabled”。此外,我添加的唯一约束是顶部、前导和尾随约束。因此,高度不是由约束定义的,这允许大小自动更改。 - Andrej

7
请使用以下代码:

Objective-C 代码

[textView setScrollEnabled:NO];

Swift代码

textView.isScrollEnabled = false

1
现在它是isScrollEnabled。无法编辑,因为这是一个太小的编辑。 - Plot
感谢建议,我已经更新了我的答案。 - Alok

3

刚修改文本调用后

[self.myText sizeToFit];

2

与UILabel不同,UITextView没有内在大小属性。所以我的做法是设置UITextView的高度约束,通过IBOutlet将其挂钩,并在textViewDidChange或文本更改时更改其值。

@IBOutlet weak var textViewHeight: NSLayoutConstraint!

func textViewDidChange(textView: UITextView) {

    // dynamic height adjustments

    var height = ceil(textView.contentSize.height) // ceil to avoid decimal

    if height != textViewHeight.constant { // set when height changed
        textViewHeight.constant = height
        textView.setContentOffset(CGPointZero, animated: false) // scroll to top to avoid "wrong contentOffset" artefact when line count changes
    }
}

但是当您输入时,您应该看到文本的末尾。使用下一行代码向底部滚动:textView.setContentOffset(CGPoint(x: 0, y: textHeight - textView.bounds.size.height), animated: true) - Roman Filippov
@RomanFilippov,这比那要棘手一些。你可能会将文本输入光标移动到顶部并在那里添加新文本。这意味着新文本可以添加到任何位置。我想缺少的一块是检测文本插入的位置并滚动到那里,可以是顶部、底部或中间某个位置。 - Hlung

1
- (void)textViewDidChange:(UITextView *)textView
{
    UIFont *myFont = [UIFont systemFontOfSize:14];
    CGSize size =   [self sizeOfText:textView.text widthOfTextView:TextviewWidth withFont:myFont];
    NSLog(@"Height : %f", size.height);
}

-(CGSize)sizeOfText:(NSString *)textToMesure widthOfTextView:(CGFloat)width withFont:(UIFont*)font
{
    CGSize ts = [textToMesure sizeWithFont:font constrainedToSize:CGSizeMake(width-20.0, FLT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
    return ts;
}

1

选择TextView并取消“滚动启用”

从顶部菜单“编辑器>大小适合内容”中选择TextView

选择其下方的视图,将其顶部约束设置为TextView底部到您想要的任何边距,然后转到“尺寸检查器”,双击或编辑刚刚添加的约束,并将“关系”设置为“大于或等于”


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接