iOS13-Swift5-UIScrollView中的keyboard适配-如何在弹出软键盘时把view向上移动键盘的高度

4,044 阅读1分钟

默认情况下,弹出软键盘时,UIScrollView(包含他的子类UITableView,UITextView,UICollectionView等)是不会自动上移的,这样会导致屏幕里靠下的内容会被软键盘挡住,用户无法实时看到自己当前输入的内容。

解决方案:让UIScrollView在软键盘弹出的时候向上移动键盘的高度

主要技术:在键盘弹出时调整scrollview中的内容的内边距--contentInset

1.以UITextView为例,注册两个观察者,分别监测键盘消失和键盘出现:

@IBOutlet weak var textView: UITextView!

override func viewDidLoad() {
    super.viewDidLoad()

    NotificationCenter.default.addObserver(self, selector: #selector(adjustKeyboard), name: UIResponder.keyboardWillHideNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(adjustKeyboard), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
    
}

2.实现方法:

@objc func adjustKeyboard(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 {
        textView.contentInset = .zero
    } else {
        //其实就是调整内边距的bottom
        textView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardViewEndFrame.height - view.safeAreaInsets.bottom, right: 0)
    }

    textView.scrollIndicatorInsets = textView.contentInset //保证滚动条和内容相对应

    let selectedRange = textView.selectedRange
    textView.scrollRangeToVisible(selectedRange) //防止在编辑UITextView时的bug
}

若不是UITextView的话可把最后两行去掉。

注:

大多数情况,我们的UITextView都是约束在safearea里面的,所以在上述调整内边距bottom的核心代码中,需减去view.safeAreaInsets.bottom,不然软键盘和UITextView内容之间会有个空档(即bottom内边距太大,要减去一部分):