Using only UIKeyboardWillChangeFrameNotification notification
Asked Answered
P

1

14

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://mcmap.net/q/502173/-ios-8-keyboard-hides-my-textview

Primateship answered 11/10, 2014 at 16:9 Comment(0)
L
36

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 their 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.

Lelahleland answered 27/12, 2014 at 7:12 Comment(6)
Is there a way to control when it scrolls? On the iphone 6 I don't need the fields to scroll when the user is editing on the top most text field but when the edit the bottom text field it should scroll to make room.Obturate
Is the use of UIViewAnimationOptions(UInt(curve)) correct? The documentation says that curve is a UIViewAnimationCurve, and looking at the definitions, this does not appear to line up with the values for UIViewAnimationOptions. Even better, the curve value returned in practice in this notification is 7 -- a private/undefined value, so a simple switch statement to convert between them won't cut it...Zweig
Is there a solution in objective-c?Retrad
@ToddHoff You would need to check which of your text fields is the current first responder inside the event handler: self.bottomTextField.isFirstResponder.Lelahleland
@DavePeck You're right, and based on my research there isn't really a great/Apple-recommended way to convert between the two. I'll update the answer with what I think is the best option as of right now (and to Swift 2).Lelahleland
I found myself needing to do this again for a new project and thought it would be a good time to update the answer for Swift 4. Happy hacking!Lelahleland

© 2022 - 2024 — McMap. All rights reserved.