效果圖
textView1.gif
主要解決2個問題:
- 鍵盤切換的之后textView父視圖frame的改變問題
- 輸入文字時textView高度的變化和父視圖frame的變化
切換鍵盤
這里切換鍵盤用到的是textView的inputView屬性,如果不給注銷和出現的方法加動畫,鍵盤改變的回調給父視圖的frame會改變兩次,出現動畫亂跳的問題,這里只能強行解決了一下
// 切換表情按鈕點擊
@objc fileprivate func changeButtonDidClick(_ button: UIButton) {
changeButton.isSelected = !button.isSelected
UIView.animate(withDuration: 0.01) {
self.textView.resignFirstResponder()
self.textView.inputView = self.textView.inputView == nil ? self.emojiView : nil
self.textView.becomeFirstResponder()
}
}
監聽鍵盤的出現和消失
// 這里監聽鍵盤的2個方法,其實可以監聽鍵盤frameWillChange
// 鍵盤將要出現
@objc fileprivate func keyboardWillShowNotification(notification: Notification) {
print(notification.userInfo!["UIKeyboardFrameEndUserInfoKey"] ?? false)
let changeFrame = notification.userInfo!["UIKeyboardFrameEndUserInfoKey"] as! CGRect
let changeHeight = changeFrame.size.height
keyboardWillShowCallBack?(changeHeight)
}
// 鍵盤將要消失
@objc fileprivate func keyboardWillHideNotification(notification: Notification) {
print(notification.userInfo!["UIKeyboardFrameEndUserInfoKey"] ?? false)
let changeFrame = notification.userInfo!["UIKeyboardFrameEndUserInfoKey"] as! CGRect
let changeHeight = changeFrame.size.height
keyboardWillHideCallBack?(changeHeight)
}
鍵盤回調方法
var inputViewHeight: CGFloat = 50 // 記錄textView的高度
var inputViewY: CGFloat = appHeight - inputViewHeight // 記錄textView的Y
var letInputViewY: CGFloat = inputViewY
let inputView = InputView(frame: CGRect(x: 0, y: inputViewY, width: appWidth, height: inputViewHeight))
// 鍵盤將要出現
inputView.keyboardWillShowCallBack = { keyboardHeight in
inputViewY = appHeight - keyboardHeight - inputViewHeight
letInputViewY = appHeight - keyboardHeight
inputView.frame = CGRect(x: 0, y: inputViewY, width: appWidth, height: inputViewHeight)
}
// 鍵盤將要消失
inputView.keyboardWillHideCallBack = { keyboardHeight in
inputViewY = appHeight - inputViewHeight
letInputViewY = appHeight
inputView.frame = CGRect(x: 0, y: inputViewY, width: appWidth, height: inputViewHeight)
}
// textView高度改變回調
inputView.textViewHeightChanged = { changeHeight in
inputViewHeight = changeHeight + 10
inputView.frame = CGRect(x: 0, y: letInputViewY - inputViewHeight, width: appWidth, height: changeHeight + 10)
}
letInputViewY 是為了記錄當鍵盤切換時Y的改變量,當textView行高發生變化的時候計算偏移的Y
inputViewHeight 是為了記錄textView改變的高度,當切換鍵盤時計算偏移的Y
解決textView自適應問題
核心代碼還是利用textView.sizeThatFits方法計算textView的新高度然后重新賦值,并回調給父視圖改變父視圖的Y即可,這里改變了一下textView的attributes屬性來調整行間距,當發送emoji表情的時候會導致emoji的高度高于計算的大小,emoji的下半邊會被遮蓋,demo沒有實現表情鍵盤
func textViewDidChange(_ textView: UITextView) {
let maxHeight: CGFloat = 90.0;
let width = textView.frame.size.width;
let newSize = textView.sizeThatFits(CGSize(width: width, height: CGFloat(MAXFLOAT)))
let textHeight = CGFloat(newSize.height)
// 修改TextView的行距和attributes
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 5
let attributes = [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 15), NSAttributedStringKey.paragraphStyle: paragraphStyle]
textView.attributedText = NSAttributedString(string: textView.text, attributes: attributes)
if textHeight <= maxHeight {
textView.isScrollEnabled = false
textView.bounds.size.height = textHeight >= 40 ? textHeight : 40 // 高度大于40的時候再高邊textView高度
textViewHeightChanged?(textView.bounds.size.height)
}else
{
textView.isScrollEnabled = true
textView.bounds.size.height = maxHeight
textViewHeightChanged?(textView.bounds.size.height)
}
}
主要為了寫個demo練習一下swift,并且養成寫簡書的習慣,剛就業不到半年的小白,借助簡書記錄自己的學習之路,代碼質量不是很高??
demo:https://github.com/qq421680227/textViewSizeFit