Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using only UIKeyboardWillChangeFrameNotification notification

Considering the new QuickType section of the keyboard.

Is it quite true that one can use ONLY a notification for UIKeyboardWillChangeFrameNotification,

and simply "not bother with" the "older" UIKeyboardWillShowNotification and UIKeyboardWillHideNotification ?

Testing seems to show it works perfectly, using ONLY keyboardFrameDidChange - but we could be missing something?

BTW here's an example of how to use UIKeyboardWillChangeFrameNotification https://stackoverflow.com/a/26226732/294884

like image 292
Fattie Avatar asked Oct 11 '14 16:10

Fattie


Video Answer


1 Answers

Updated for Swift 5 on 2021-05-17

It is definitely possible and can cut your code just about in half. The following example uses Auto Layout for a lot of the heavy lifting.

NotificationCenter.default.addObserver(
    forName: UIResponder.keyboardWillChangeFrameNotification,
    object: nil,
    queue: nil
) { (notification) in
    guard let userInfo = notification.userInfo,
          let frameEnd = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect,
          let curveRaw = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? Int,
          let curve = UIView.AnimationCurve(rawValue: curveRaw),
          let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval
    else { return }

    // Convert the frame rects you're interested in to a common coordinate space
    let keyboardRect = self.view.convert(frameEnd, from: nil)
    let formContainerRect = self.view.convert(self.formContainerView.frame, from: nil)

    // Calculate their intersection and adjust your constraints accordingly
    let intersection = keyboardRect.intersection(formContainerRect)
    if !intersection.isNull {
        // Some overlap; adjust the bottom of your views (what you do here will vary)
        self.formContainerBottomConstraint?.constant = intersection.size.height
    } else {
        // No overlap; reset your views to its default position
        self.formContainerBottomConstraint?.constant = 0
    }

    let animator = UIViewPropertyAnimator.init(duration: duration, curve: curve) {
        self.view.layoutIfNeeded()
    }
    animator.startAnimation()
}

self.formContainerBottomConstraint is a NSLayoutConstraint that binds the bottom of my (imaginary) form to the bottom of my view. This code animates the field up when the keyboard appears and down when it disappears.

All of that was possible in iOS < 8 by using a combination of UIKeyboardWillShowNotification and UIKeyboardWillHideNotification. But! As you say, iOS 8 introduced the QuickType section which can be collapsed or expanded by the user. This solution is super versatile and will let your app respond to whatever keyboard changes the OS throws your way.

like image 144
adamrothman Avatar answered Sep 21 '22 04:09

adamrothman