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

"Hello world"

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

"Goodbye world"

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

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


当前回答

对于iOS 7.0,不是将frame.size.height设置为contentSize. height。使用[textView sizeToFit]。

看这个问题。

其他回答

The easiest way to ask a UITextView is just calling -sizeToFitit should work also with scrollingEnabled = YES, after that check for the height and add a height constraint on the text view with the same value. Pay attention that UITexView contains insets, this means that you can't ask the string object how much space it want to use, because this is just the bounding rect of the text. All the person that are experiencing wrong size using -sizeToFit it's probably due to the fact that the text view has not been layout yet to the interface size. This always happen when you use size classes and a UITableView, the first time cells are created in the - tableView:cellForRowAtIndexPath: the comes out with the size of the any-any configuration, if you compute you value just now the text view will have a different width than the expected and this will screw all sizes. To overcome this issue I've found useful to override the -layoutSubviews method of the cell to recalculate textview height.

使用UITextViewDelegate是最简单的方法:

func textViewDidChange(_ textView: UITextView) {
    textView.sizeToFit()
    textviewHeight.constant = textView.contentSize.height
}

不知道为什么人们总是把事情复杂化: 下面就是:

- (void)textViewDidChange:(UITextView *)textView{ CGRect frame = textView.frame;
CGFloat height = [self measureHeightOfUITextView:textView];
CGFloat insets = textView.textContainerInset.top + textView.textContainerInset.bottom;
height += insets;
frame.size.height = height;

if(frame.size.height > textView.frame.size.height){
    CGFloat diff = frame.size.height - textView.frame.size.height;
    textView.frame = CGRectMake(5, textView.frame.origin.y - diff, textView.frame.size.width, frame.size.height);
}
else if(frame.size.height < textView.frame.size.height){
    CGFloat diff = textView.frame.size.height - frame.size.height;
    textView.frame = CGRectMake(5, textView.frame.origin.y + diff, textView.frame.size.width, frame.size.height);
}
[textView setNeedsDisplay];
}

结合迈克·麦克马斯特的回答,你可能会想这样做:

[myTextView setDelegate: self];

...

- (void)textViewDidChange:(UITextView *)textView {
  if (myTextView == textView) {
     // it changed.  Do resizing here.
  }
}

用键值观察(KVO)很简单,只需创建UITextView的子类,然后做:

private func setup() { // Called from init or somewhere

    fitToContentObservations = [
        textView.observe(\.contentSize) { _, _ in
            self.invalidateIntrinsicContentSize()
        },
        // For some reason the content offset sometimes is non zero even though the frame is the same size as the content size.
        textView.observe(\.contentOffset) { _, _ in
            if self.contentOffset != .zero { // Need to check this to stop infinite loop
                self.contentOffset = .zero
            }
        }
    ]
}
public override var intrinsicContentSize: CGSize {
    return contentSize
}

如果你不想子类化,你可以尝试做textView。bounds = textView。contentSize观察者中的contentSize。