-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
useAnimatedKeyboard fixes (iOS) #6755
useAnimatedKeyboard fixes (iOS) #6755
Conversation
606096c
to
3c2d160
Compare
Hi @mhoran, thanks for another PR! Someone from Reanimated team will review this PR shortly. Would you mind giving us a bit more context on why exactly some of the changes were made (e.g. what's the reason to change |
Sure thing! I tried to leave detailed notes in my commit messages for posterity, but happy to provide further context as well. Regarding I found that the most reliable way to determine if the keyboard has been detached is to listen for However, this approach also has the benefit of simplifying the logic in the change handler. I was able to remove the logic that tried to guess whether the keyboard was opening or closing -- which I found to be inaccurate at times, especially when a hardware keyboard is attached (due to the autosuggest dock.) The I fixed a few more issues along the way.
There is a new API, Keyboard Layout Guide, which will make this all a lot simpler in the future. However, it was introduced in iOS 15. So we will have to live with this complexity until RN 0.76 is the oldest supported version for Reanimated. Note that there remain some issues with undocked and split keyboard modes, due to incorrect start frame positions sent in notifications. Apple has removed these modes in new devices, so I didn't try to implement workarounds. |
Here is a screen recording showing the improvements: https://drive.google.com/file/d/1EFDhYZWNMXhJIwNlj1_ugeVwe3FqZqVF/view?usp=drivesdk. |
ddefb46
to
b6c8364
Compare
It seems I may also have fixed #6727 as I was cleaning things up in 9f6b546. When a hardware keyboard is connected and the autocorrect bar is on screen, the keyboard is considered "open". But when you show the on screen keyboard, it rapidly hides and then shows the keyboard -- inadvertently triggering the interactive dismissal logic. Cleaning up the interactive dismissal flags fixed this for the hardware keyboard case, and I believe it should fix the scenario described in #6727 as well. |
bc3d884
to
22aee6a
Compare
I tested this in my app and can confirm it does fix the Prefer Cross Fade Transition issue (#6440) |
22aee6a
to
bc3d884
Compare
There is an issue with iOS 18.2 when opening the on-screen keyboard from the autosuggest bar when a hardware keyboard is attached. Opening the on-screen keyboard in this way will not properly update the height returned by |
0c778e8
to
9f6b546
Compare
I managed to fix the iOS 18.2 hardware keyboard issue by updating the keyboard height in response to This has cleaned up keyboard state handling as well. Now state changes are handled only by the corresponding notification handlers, and On a side note, I managed to get the |
7c9a7c0
to
5a6a72f
Compare
@mhoran Thanks again for your work on this PR. We're quite focused on other areas but we'll try to find some availability to review and thoroughly test your changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, an incredible PR and I wish more folks from community made such impressive contributions!
I've left some rather stylistic comments to make sure the code is anyhow readable in the future, since most of the stuff we do here is already pretty hacky.
I am yet to test everything I need on a physical iPad, I'll get that done tomorrow most likely.
Nonetheless, great work!
.../react-native-reanimated/apple/reanimated/apple/keyboardObserver/REAKeyboardEventObserver.mm
Show resolved
Hide resolved
.../react-native-reanimated/apple/reanimated/apple/keyboardObserver/REAKeyboardEventObserver.mm
Outdated
Show resolved
Hide resolved
.../react-native-reanimated/apple/reanimated/apple/keyboardObserver/REAKeyboardEventObserver.mm
Outdated
Show resolved
Hide resolved
Also, I found that the height values emitted when undocking the keyboard are some quite rough jumps.
floating_jumps.mp4I wonder if we could maybe force a animation, just like you did with the canceled interactive dismiss. |
Previously, when the keyboard was detached, useAnimatedKeyboard returned a height corresponding to the height of a docked keyboard. However, when the keyboard is floating, undocked or split, the height should be 0. Listen for the UIKeyboardWillHideNotification notification to determine if the keyboard has been detached. We must now listen for show and hide notifications instead of UIKeyboardWillChangeFrameNotification, as the show/hide notifications are dispatched after the change frame notification. Adapted from the initial work in software-mansion#5710. Listening for hide is simpler than calculating whether the keyboard is detached, compatible with Stage Manager, and maintains compatibility with interactive keyboard dismissal.
When processing a keyboard frame, if the keyboard did not animate to the target height (e.g. when closing the software keyboard on a device with a physical keyboard), the height would be set to the wrong value in updateKeyboardFrame on the subsequent update. Instead of relying on the measuringView, which refers to the closing animation in such cases, return _targetKeyboardHeight, which is also returned in keyboardWillChangeFrame.
The keyboard frame passed to keyboardWillChangeFrame is in the screen's coordinate space [1]. Convert to the window's coordinate space to support Stage Manager. https://developer.apple.com/documentation/uikit/uikeyboardframeenduserinfokey?language=objc
When the keyboard is dismissed via the close button or is undocked, the interactive dismissal observer will be notified of the geometry change before the show/hide notification is received. Bail out before updating the keyboard height if the reported keyboard height is 0, if the keyboard state is CLOSED or if the keyboard is floating (keyboard width != window width.) Note that this still allows some updates through when they shouldn't be, but it's better than before, especially for floating keyboards.
The interactive dismissal logic would get tripped up if the keyboard was rapidly opened and closed, which can happen if a hardware keyboard is used and the autosuggest dock appears and then disappears when the on screen keyboard is opened. Fixes software-mansion#6727.
UIKeyboardDidShowNotification on iOS 18.2 returns an incorrect end frame origin when opening the on-screen keyboard from the shortcuts bar when a hardware keyboard is attached. Instead of relying on this incorrect frame, return the height of the keyboard view in response to UIKeyboardDidShowNotification and 0 in response to UIKeyboardDidHideNotification. State changes are now completely handled in response to notifications, and updateKeyboardFrame is only responsible for animation tracking.
5a6a72f
to
9bf43f3
Compare
Thanks again for the review @szydlovsky. I believe I have addressed all your concerns. I was able to fix the floating keyboard animation by always animating if the keyboard event has a duration and adding another check to the interactive dismiss logic to not update height if the state is |
For the record, the changes regarding jumping midpoints when transitioning from attached to detached keyboard turned out to be inconsistent. On some devices they fixed stuff, on others did nothing and we believe it just added unnecessary complexity. Thus, the logic from that commit is gonna be rolled back, but the comments stay here |
9bf43f3
to
09562c6
Compare
Unfortunately, I found a more severe mismatch with interactive dismiss emitted values - they seem to be quite a bit off 😢 mismatch.mp4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After quite a bit of testing, looks and works great, fixes exactly what it is supposed to and introduces no regressions. Beautiful 🎉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mhoran Thanks again for the PR!
Summary
fix: return correct height for detached keyboard on iOS (fixes #5584, #6440)
fix: don't clobber keyboard height when keyboard did not animate on iOS
fix: convert keyboard position to window coordinate space on iOS (Stage Manager compatibility)
fix: don't prematurely update keyboard height during dismissal on iOS
fix: don't jump to height when iOS keyboard is rapidly opened/closed (fixes #6727)
fix: correct height when keyboard opened from shortcuts bar on iOS
Test plan
Can be tested with the useAnimatedKeyboard example.