当在UITextView内输入时如何调整其大小?

15

我正在创建一个评论区,就像Facebook在它的iOS应用程序中用于消息部分的评论区。我希望UITextView可以调整高度,以便我输入的文本适合它,而不是您必须滚动查看溢出的文本。有什么想法可以做到这一点吗?我已经研究过可能使用CGRect来分配给文本视图的大小和高度,然后匹配内容大小:

CGRect textFrame = textView.frame;
textFrame.size.height = textView.contentSize.height;
textView.frame = textFrame;

我假设我需要一些函数来检测文本何时到达了 UITextView 的边界,然后调整视图的高度?有人遇到过这个同样的概念吗?


你可以在这里找到详细的工作解决方案。 - malex
5个回答

23

您可以在此委托方法中调整框架大小,不要忘记将textView的委托设置为self。

-(BOOL)textView:(UITextView *)_textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
      [self adjustFrames];  
      return YES;
}


-(void) adjustFrames
{
   CGRect textFrame = textView.frame;
   textFrame.size.height = textView.contentSize.height;
   textView.frame = textFrame;
}

这个解决方案适用于iOS6及以前的版本...如需针对iOS7,请参考此处

StackOverflow答案


哦,真的吗?我没想到会那么简单。好的,谢谢,我会试一试! - Ollie177
为了在iOS 7+中正常工作,请在- (void)textViewDidChange:(UITextView *)textView中添加adjustFrames - Fahim Parkar

8
这是我的解决方案,使用自动布局textView.contentSize.height。在iOS8 Xcode6.3 beta4上进行了测试。
关于最后的setContentOffset有一个需要注意的地方。我放置它是为了避免当行数改变时出现“错误的contentOffset”现象。它会在最后一行下面添加一个额外的空格,看起来不太好,除非你在改变约束后将其设置回去。我花了几个小时才弄清楚这一点!
// set this up somewhere
let minTextViewHeight: CGFloat = 32
let maxTextViewHeight: CGFloat = 64

func textViewDidChange(textView: UITextView) {

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

    if (height < minTextViewHeight + 5) { // min cap, + 5 to avoid tiny height difference at min height
        height = minTextViewHeight
    }
    if (height > maxTextViewHeight) { // max cap
        height = maxTextViewHeight
    }

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

textViewHeight 声明在哪里? - lf215
1
@lf215 这是一个用于 UITextView 高度的 NSLayoutConstraint 对象。我忘记添加了,抱歉。 - Hlung
我对这个还比较新,请问您能否详细说明/添加更多代码以展示如何获取textViewHeight? - lf215
1
如果您正在使用Storyboard,则会像@IBOutlet weak var textViewHeight: NSLayoutConstraint!这样成为一个IBOutlet变量,您可以将其连接到界面构建器中的UITextView的高度约束。 - Hlung
这对我来说已经很好了,我很满意,但我想知道是否有一些小的改变可以使它变得更好。光标似乎总是垂直居中。这在一行时看起来不错:dropbox.com/s/dwjbjhcm80a6co5/Screenshot%202016-09-28%2022.54.10.png,但在两行时就不太好看了:https://www.dropbox.com/s/7216694bohuqfin/Screenshot%202016-09-28%2022.57.17.png 理想情况下,第二行应该保持平坦在底部。我认为这是因为光标垂直居中的缘故。 - lf215
这个对我来说几乎有效,但在设置约束和内容偏移之间,我不得不添加这一行:textView.bounds.size.height = textView.contentSize.height。另外我注意到使用 textView.contentOffset = CGPointZero 是无效的。 - Nickkk

5

在持有UITextView的TableViewController中,更新从tableViewDataSource获取并放入单元格中的数据,然后只需调用此方法:

tableView.beginUpdates()
tableView.endUpdates()

与tableView.reloadData()不同,此方法不会调用resignFirstResponder。

太完美了!谢谢。这是 ObjC 版本:- (void)textViewDidChange:(UITextView *)textView { [self.tableView beginUpdates]; [self.tableView endUpdates]; } 你甚至可以免费获得动画效果 ;) - Holtwick

5

首先将TextView的最小高度约束设置为:

textView.heightAnchor.constraint(greaterThanOrEqualTo: view.heightAnchor, multiplier: 0.20)

(确保您设置了greaterThanOrEqualTo约束,以便如果内在内容高度大于此高度,则采用内在内容高度)
或者简单的常量
textView.heightAnchor.constraint(greaterThanOrEqualToConstant: someConstant)

在配置textView时,将isScrollEnabled设置为false。
textView.isScrollEnabled = false

现在当您在textView上输入时,它的内在内容大小高度将增加,并且它将自动推动下面的视图。

调整文本视图高度的最佳答案之一。 - CodeChanger

1

contentsize 在iOS 7中不起作用。 尝试这样做:

CGFloat textViewContentHeight = textView.contentSize.height;

 textViewContentHeight = ceilf([textView sizeThatFits:textView.frame.size].height + 9);

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