Search code examples
swiftuiscrollviewios11

Extend UIScrollView insets behind keyboard on iOS11


Since Apple introduced safe area insets and adjusted content insets the already working UI layouting code becomes broken. In my case UIScrollView bottom inset extends when the keyboard appears:

func keyboardWillResize(_ notification: Notification) {
    let info: [AnyHashable: Any] = notification.userInfo!
    let keyboardTop = self.view.frameOnScreen.maxY - (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.y
    UIView.animate(withDuration: 0.3, animations: {
        self.tableView.contentInset.bottom = keyboardTop
        self.tableView.scrollIndicatorInsets = self.tableView.contentInset
    })
}

Within iOS 11 this code produces extra inset when keyboard appears, equal to tab bar height. It's obvious because now contentInset represents only user-defined insets, and real insets are represented by adjustedContentInset introduced in iOS 11.

So my question is how to deal with this case in good manner? There is option to write

self.tableView.contentInset.bottom = keyboardTop - self.tableView.adjustedContentInset.bottom

but it looks so ugly. Maybe there is built-in method to extend insets behind the keyboard?


Solution

  • Obviously, the answer is in official documentation. Instead of manually adjust content insets, we should delegate this stuff to view controller and deal with it's safe area insets. So, here is working code:

    func keyboardWillResize(_ notification: Notification) {
        let info: [AnyHashable: Any] = notification.userInfo!
        let keyboardTop = self.view.frameOnScreen.maxY - (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.y
        UIView.animate(withDuration: 0.3, animations: {
            self.additionalSafeAreaInsets.bottom = max(keyboardTop - self.view.safeAreaInsets.bottom, 0)
        })
    }