最近在專案中需要解決蘋果系統輸入法遮擋輸入框的問題,預期結果為:
- 若鍵盤彈出后會遮擋輸入框,則輸入框隨鍵盤彈起上移,輸入法切換時輸入框始終保持在距鍵盤上方 4pt 處;
- 若鍵盤彈出后不會遮擋輸入框,但切換輸入法后會遮擋輸入框,則輸入框需要在切換后上移,隨后輸入法切換時輸入框始終保持在鍵盤上方 4pt 處,
效果示意:/待補充/
一. 背景
開發環境:iOS14.2 + Xcode v12.2 + Swift5
設備:iPhoneSE(其他機型測驗有效)
頁面采用自動布局
頁面結構:/待補充/
二. 實作方式
在viewWillAppear中添加鍵盤彈出、收起、frame變化的通知
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// 鍵盤彈出監聽,解決鍵盤擋住輸入框的問題
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillAppear),
name: UIResponder.keyboardWillShowNotification,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardHasAppear),
name: UIResponder.keyboardDidShowNotification,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillDisappear),
name: UIResponder.keyboardWillHideNotification,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardFrameDidChange),
name: UIResponder.keyboardDidChangeFrameNotification,
object: nil)
}
(相關鏈接:iOS鍵盤通知)
添加成員變數:
private var keyboardFlag: Int = 0 // 鍵盤彈起情況,收起=0
private var deltaHeight: CGFloat = 0 // 鍵盤與輸入框間距
private var nameFieldBottomHeight: CGFloat = 0 // 輸入框底部到頁面底部距離
private var transformDistance: CGFloat = 0 // 頁面移動距離
實作 keyboardWillAppear:
@objc
func keyboardWillAppear(noti: Notification) {
// 獲得軟鍵盤的高
let keyboardSize = (noti.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
let keyboardHeight = keyboardSize?.height
// 計算輸入框和軟鍵盤的高度差
let rect = self.nickNameEditView.containerView
.convert(self.nickNameEditView.containerView.bounds,
to: self.view) // 將rect由rect所在視圖轉換到目標視圖view中,回傳在目標視圖view中的rect
self.nameFieldBottomHeight = self.view.bounds.height - (rect.origin.y + rect.size.height)
self.deltaHeight = (keyboardHeight ?? 0) - self.nameFieldBottomHeight
if self.keyboardFlag == 0, self.deltaHeight > 0 { // 鍵盤原來是收起的,且遮擋輸入框
self.pageContainerView.transform = CGAffineTransform(a: 1, b: 0, c: 0, d: 1,
tx: 0, ty: -self.deltaHeight - 4)
self.transformDistance = -self.deltaHeight - 4
/* -4:為了使鍵盤距離輸入框底部距離為4pt,該值可改 */
}
}
實作keyboardHasAppear:
@objc
func keyboardHasAppear() {
self.keyboardFlag = 1 // 鍵盤已彈出
}
實作keyboardWillDisappear:
@objc
func keyboardWillDisappear() {
if self.keyboardFlag == 0 {
// 軟鍵盤收起的時候恢復原始偏移
self.pageContainerView.transform = CGAffineTransform.identity
self.transformDistance = 0
}
}
實作 keyboardFrameDidChange,解決切換輸入法動態調整:
@objc
func keyboardFrameDidChange(noti: Notification) {
// 獲得軟鍵盤的高
let keyboardSize = (noti.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
let keyboardHeight = keyboardSize?.height
// 計算輸入框和軟鍵盤的高度差
self.deltaHeight = (keyboardHeight ?? 0) - (self.nameFieldBottomHeight + self.transformDistance)
// 鍵盤在彈出的情況下如果frame有變化就改變輸入框位置
if self.keyboardFlag == 1 {
// 如果頁面之前沒有上移,鍵盤遮擋輸入框,頁面上移; 頁面之前有上移,輸入框下降到鍵盤上方4pt處
if (self.transformDistance == 0 && self.deltaHeight > 0) || (self.transformDistance != 0) {
self.pageContainerView.transform = CGAffineTransform(a: 1, b: 0, c: 0, d: 1,
tx: 0, ty: -self.deltaHeight - 4)
self.transformDistance = -self.deltaHeight - 4
}
}
}
點擊空白區域收取鍵盤:
// 收起鍵盤
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if self.nickNameEditView.nameTextField.isFirstResponder {
self.keyboardFlag = 0
self.nickNameEditView.nameTextField.resignFirstResponder()
}
}
在 viewWillDisappear 中移除通知:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardDidShowNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardDidChangeFrameNotification, object: nil)
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/226901.html
標籤:其他
上一篇:NDK入門——第一個JNI程式
