kirillzyusko / react-native-keyboard-controller

Keyboard manager which works in identical way on both iOS and Android
https://kirillzyusko.github.io/react-native-keyboard-controller/
MIT License
1.62k stars 67 forks source link

KeyboardAwareScrollView sometimes has no bottom padding on iOS #463

Closed z0w0 closed 1 month ago

z0w0 commented 4 months ago

Describe the bug Thanks for your work on the library! We use it across our app, mainly KeyboardAwareScrollView and on some screens KeyboardAwareScrollView + KeyboardStickyView for a sticky footer.

One issue that we've been stuck trying to track down, is the KeyboardAwareScrollView component sometimes adds no padding at the bottom of the view. As far as we're aware this is only happening on iOS. We are struggling to reliably reproduce this.

I've done some digging, and when I do manage to get my local version of the app in a broken state what I've found is that the onMove native event in the useKeyboardHandler is not being emitted by the native code in the library. Since the padding depends on this event to know how much height to add, that checks out. The onKeyboardMoveStart and onKeyboardMoveEnd events are still being triggered, just for some reason not onKeyboardMove.

Code snippet In the below, currentKeyboardFrameHeight.value is always set to 0 even when the keyboard is open/opening on iOS, so only 1px of padding is added. currentKeyboardFrameHeight.value is updated by the onMove event handler.

    const view = useAnimatedStyle(
      () => enabled
          ? {
              // animations become choppy when scrolling to the end of the `ScrollView` (when the last input is focused)
              // this happens because the layout recalculates on every frame. To avoid this we slightly increase padding
              // by `+1`. In this way we assure, that `scrollTo` will never scroll to the end, because it uses interpolation
              // from 0 to `keyboardHeight`, and here our padding is `keyboardHeight + 1`. It allows us not to re-run layout
              // re-calculation on every animation frame and it helps to achieve smooth animation.
              // see: https://github.com/kirillzyusko/react-native-keyboard-controller/pull/342
              paddingBottom: currentKeyboardFrameHeight.value + 1, // <-- SET TO 1 WHEN BROKEN
            }
          : {},
      [enabled],
    );

Repo for reproducing Can't reproduce consistently - see below

To Reproduce Unfortunately it's really difficult to reproduce the behaviour and what we're seeing. It seems to work a majority of the time, but something triggers the broken state. It's almost like the keyboard move listener is being unregistered somehow? Let me know if you have any advice on how to hunt down a reproduction for this and I can update the issue with a link to the reproduction.

Expected behavior The scroll view should always have padding added to it based on the keyboard height. Without it content is never shifted up.

Smartphone (please complete the following information):

kirillzyusko commented 4 months ago

Thank you @z0w0 for a detailed issue. Actually it's very strange that keyboard padding is not added, but let me ask you several questions:

https://github.com/kirillzyusko/react-native-keyboard-controller/blob/0e41662f4225cb82a3783ca7ba2b0be5c6377c8a/ios/observers/KeyboardMovementObserver.swift#L317-L323

If you are saying, that onStart/onEnd are dispatched, it means that observer in native code is actually registered. The only one question is why onMove is not triggered.

On iOS I track onMove in next way - I wait for keyboardWillShow event and set up CADisplayLink with updateKeyboardFrame callback. This callback gets fired each frame and in this callback I read keyboard frame values.

The code is very straightforward and should be easy to debug, I believe. May I ask you to check:

z0w0 commented 4 months ago

Thanks for the prompt reply - will take a look into your debugging suggestions and see if I can find anything else. In the meantime here's some example screen recordings:

Working - this is how this one screens moves when it's working

https://github.com/kirillzyusko/react-native-keyboard-controller/assets/676417/27bb89f5-0871-44f7-b5e4-2e8ff11939b6

Not working - the same screen, but in the broken state. The keyboard still animated in but no padding was added.

https://github.com/kirillzyusko/react-native-keyboard-controller/assets/676417/e62167a5-34d8-48a4-afd1-1dd81a91fd83

kirillzyusko commented 4 months ago

@z0w0 if we compare first frame and second frame, then I clearly can see that TextInput starts to move, but all subsequent frames gets ignored 🤔 So for me it looks like maybeScroll gets called somewhere in the code 🤔

First frame Second frame
image image

Another suspicious thing is that in the end you can scroll to the bottom and input will be above the keyboard - it makes me thinking that currentKeyboardFrameHeight.value actually gets updated. Because otherwise the input should be obscured by the keyboard. But correct me if I'm wrong 🙌

z0w0 commented 4 months ago

Ahh I think you're right and the recording has the padding - so might actually be a different issue in that recording. But there are definitely other situations where there's no padding. I'll keep trying to debug/reproduce using the info and get back to you. Thanks again for your help!

kirillzyusko commented 3 months ago

@z0w0 I published a new version 1.12.3 where I improved the algorithm for searching a keyboard view - would you mind to test it against a new version and see if bug is present? (not sure if it fixes the issue for you, but worth to try 😊)

z0w0 commented 3 months ago

Awesome thanks @kirillzyusko - will upgrade to it and give it a try. I still haven't managed to find a reproduction for the original issue I described in the issue, but for the video recording I sent you that actually turned out to be a separate issue. And was fixed in 1.12.2 as part of your fix here

Fingers crossed 1.12.3 will resolve the main issue.

Will keep you updated once I get some more info

kirillzyusko commented 3 months ago

@z0w0 cool, keep me updated, please 👍

Also, if you reproduce the bug - don't hesitate to share a video here. Maybe just by looking on a video I will understand where is the problem or at least can give a direction for further investigation 👀

kirillzyusko commented 1 month ago

@z0w0 may I know the status of this problem? Was it fixes in 1.12.3? If not, then maybe you can provide additional information? Like sharing video, because you said, that attached videos contained a different problem that has been fixed - so if you can add an actual video with the bug I would highly appreciate you!

z0w0 commented 1 month ago

We haven't seen it since we upgraded, so yep all good to close it. Thanks for your help!