原文鏈接:
https://www.hackingwithswift.com/read/19/7/fixing-the-keyboard-notificationcenter
實現(xiàn)代碼:
class ViewController: UIViewController {
lazy var script: UITextView = {
let d = UITextView(frame: UIScreen.main.bounds)
return d
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.addSubview(script)
addNotifi()
}
@objc func addNotifi() {
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(adjustForKeyboard), name: UIResponder.keyboardWillHideNotification, object: nil)
notificationCenter.addObserver(self, selector: #selector(adjustForKeyboard), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
}
@objc func adjustForKeyboard(notification: Notification) {
guard let keyboardValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return }
let keyboardScreenEndFrame = keyboardValue.cgRectValue
let keyboardViewEndFrame = view.convert(keyboardScreenEndFrame, from: view.window)
if notification.name == UIResponder.keyboardWillHideNotification {[圖片上傳中...(QQ20200516-162120.gif-b5310a-1589617305797-0)]
script.contentInset = .zero
} else {
script.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardViewEndFrame.height - view.safeAreaInsets.bottom, right: 0)
}
script.scrollIndicatorInsets = script.contentInset
let selectedRange = script.selectedRange
script.scrollRangeToVisible(selectedRange)
}
}
實現(xiàn)原理:
我們可以要求使用新的類來告知鍵盤狀態(tài)何時更改NotificationCenter
施逾。在幕后,iOS會在發(fā)生事情時不斷發(fā)出通知-鍵盤更換,應(yīng)用程序移至后臺以及應(yīng)用程序發(fā)布的任何自定義事件遭商。我們可以將自己添加為某些通知的觀察者琅摩,并且在通知發(fā)生時將調(diào)用我們命名的方法蚜枢,甚至將傳遞任何有用的信息径荔。
使用鍵盤時休讳,我們關(guān)注的通知是keyboardWillHideNotification
和keyboardWillChangeFrameNotification
主届。當(dāng)鍵盤完成隱藏時赵哲,將發(fā)送第一個,而在發(fā)生任何鍵盤狀態(tài)更改時將顯示第二個君丁,包括顯示和隱藏枫夺,還包括方向,QuickType
等绘闷。
這聽起來就像我們并不需要keyboardWillHideNotification
橡庞,如果我們有keyboardWillChangeFrameNotification
,但在我的測試僅僅使用keyboardWillChangeFrameNotification
是不夠的簸喂,趕上連接硬件鍵盤”兴溃現(xiàn)在,這是一種極為罕見的情況喻鳄,但我們還是可以肯定的扼倘!
為了將自己注冊為通知的觀察者,我們獲得了默認(rèn)通知中心的引用。然后addObserver()
再菊,我們使用self帶有四個參數(shù)的方法:應(yīng)接收通知的對象(是)爪喘,應(yīng)調(diào)用的方法,我們要接收的通知以及我們要監(jiān)視的對象纠拔。我們將傳遞nil到最后一個參數(shù)秉剑,表示“我們不在乎誰發(fā)送通知”。
該adjustForKeyboard()
方法很復(fù)雜稠诲,但這是因為它有很多工作要做侦鹏。首先,它將接收類型為的參數(shù)Notification
臀叙。這將包括通知的名稱略水,以及Dictionary
包含名為的通知特定信息userInfo
。
使用鍵盤時劝萤,字典中將包含一個名為UIResponder.keyboardFrameEndUserInfoKey
的鍵渊涝,可以在動畫完成后告訴我們鍵盤的框架。這將是類型NSValue
床嫌,而后者又是類型CGRect
跨释。該CGRect
結(jié)構(gòu)同時包含a CGPoint
和a CGSize
,因此可用于描述矩形厌处。
Objective-C
的一個怪癖是數(shù)組和字典不能包含諸如的結(jié)構(gòu)CGRect
鳖谈,因此Apple
有一個稱為的特殊類NSValue
,它充當(dāng)結(jié)構(gòu)的包裝阔涉,因此可以放入字典和數(shù)組中蚯姆。這就是這里發(fā)生的事情:我們正在獲取一個NSValue
對象,但是我們知道它包含一個CGRect
內(nèi)部洒敏,因此我們使用其cgRectValue
屬性讀取該值龄恋。
一旦我們最終拉出正確的鍵盤框架,就需要將矩形轉(zhuǎn)換為視圖的坐標(biāo)凶伙。這是因為旋轉(zhuǎn)沒有考慮到框架中郭毕,所以如果用戶在風(fēng)景中,我們將翻轉(zhuǎn)寬度和高度-使用該convert()
方法可以解決該問題函荣。
我們在該adjustForKeyboard()
方法中需要做的下一件事是調(diào)整文本視圖的contentInset
和scrollIndicatorInsets
显押。這兩個本質(zhì)上縮進(jìn)了文本視圖的邊緣,因此傻挂,即使其約束在視圖中仍然是邊到邊乘碑,它似乎也占據(jù)了更少的空間。
最后金拒,我們將使文本視圖滾動兽肤,以使文本輸入光標(biāo)可見套腹。如果文本視圖縮小,則現(xiàn)在將不在屏幕上资铡,因此再次滾動查找以保持用戶體驗不變电禀。
如您所見,使用UIEdgeInsetsstruct
完成文本視圖的插入設(shè)置笤休,該結(jié)構(gòu)需要所有四個邊緣的插入尖飞。我使用文本視圖的內(nèi)容插圖scrollIndicatorInsets
來節(jié)省時間。
請注意店雅,其中存在的檢查政基,這UIKeyboardWillHide
是通過將插入項顯式設(shè)置為零來連接硬件鍵盤的解決方法。
實現(xiàn)效果: