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]