iOS 一个比较完美的 Growing TextViewgit
如今都 2019 年了,App 中使用自动增高的输入框已经很常见了,即时通信的 Chat 界面、社交类 App 的评论功能均可以看到自增高输入框。但写出一个自增高输入框容易,写好难。如今市面上一些主流 App 的输入框依然会有一些瑕疵,例如:文字挡住一部分、粘贴大量文字时出现偏移,具体问题下面详细分析。github
如今 iOS 开发已通过了搭建 UI 和普通业务功能的初级阶段,App 要想赢得用户的青睐,除了 App 的功能、UI 设计,交互体验的细节处理相当重要。通常用户只要使用输入框能正常输入便可,90% 的用户不会察觉输入框的一些细节,但做为开发人员应该知道这些细节(bug)并作出处理。bash
这个问题严格来讲算 bug,毕竟粘贴仍是一个很常见的操做。测试
一个输入框要么显示 N 行文字、要么显示 N + 1行,若是显示 N + 0.5 行就有点难以想象了。这个问题对 App 功能没有任何影响,但这么多 App 居然都有这个问题并且很是广泛,是我始料未及的。测试了多个 App 后,只有QQ的输入框作的最好,粘贴、遮挡文字等问题根本不存在。ui
写出一个自增高的输入框仍是比较容易的,大体过程就是给 textView 添加左、右、下/上、高度四个约束,而后监听文字变化的通知,进而修改输入框的高度。若是想写好,就要花时间打磨了。我接下来主要说一下你们可能遇到的一些细节问题。spa
个人作法是继承 UITextView
重写 setBounds
方法,从新调整contentOffset
设计
- (void)setBounds:(CGRect)bounds
{
[super setBounds:bounds];
// NSLog(@"bounds:%@", NSStringFromCGRect(bounds));
if (self.contentSize.height <= self.bounds.size.height + 1){
self.contentOffset = CGPointZero; // Fix wrong contentOfset
} else if (!self.tracking) {
CGPoint offset = self.contentOffset;
if (offset.y > self.contentSize.height - bounds.size.height) {
offset.y = self.contentSize.height - bounds.size.height;
if (!self.decelerating && !self.tracking && !self.dragging) {
self.contentOffset = offset;
}
// Fix wrong contentOfset when paster huge text
}
}
}
复制代码
正常状况下滚动输入框的文字,文字能够滚动到控件顶部。而 QQ 的输入框,无论怎么滑动文字,文字和输入框顶部都有一段固定间隔。3d
先了解输入框的一个属性textContainerInset
,这个值默认是 (8, 0, 8, 0),就是说默认状况下文字和输入框顶部有 8pt 的偏移,因此当文字输入较多的时候文字向上滚动,那么文字和控件顶部间隙会减少到 0。code
实现QQ输入框的效果,我能想到的方案是把textContainerInset
全设置为 0(或者top/bottom为0),这样文字就紧挨着输入框,文字和输入框顶部的固定间距就是 0 了。接着要给UITextView
添加一个 containerView
,containerView
竖向比 UITextView
高出一部分,从而实现 顶部/底部 的固定间距。cdn
这个问题是由于 单行文字高度 * 最大行数 != 输入框的最大高度
,输入框的最大高度可不是随便设置的,先肯定输入框的font
和最大行数,font.lineHeight * 行数
就是输入框的最大高度。这样就不会出现文字挡住一部分的问题了
接下来就是我本身写的自增高输入框了,目前没发现什么问题,至少没有上面涉及的问题。
[Reference]