Skip to content

Using KeyboardAwareScrollView on BottomSheet #789

@xotahal

Description

@xotahal

Describe the bug
There is a problem with calculating position of text input when used on bottom sheet component (@gorhom/bottom-sheet). Let me explain what's happening with these two videos.

When I fully open the bottom sheet then everything seems to be fine.

Screen.Recording.2025-01-30.at.3.51.02.PM.mov

When I make the bottom sheet smaller than keyboard it scrolls wrong. You can see when I press input 0, the bottom sheet itself extend to fully open position and that means the KeyboardAwareScrollView should do nothing, because eventually the 0 input is above the keyboard.

The same behaviour happening even after I hide keyboard and focus the same #0 input. Only after I change to 1 input it works fine and it also works fine if I focus 0 field after I focused 1 field.

Hope it makes sense.

Screen.Recording.2025-01-30.at.3.51.36.PM.mov

Code snippet
I am looking at the code and I think I know what the problem is. I am happy to fix it and prepare PR, but I would maybe appreciate some guidance so the PR meets expectations. I think there might be multiple problems with this kind of use case (including the PR I created already - #770 - I would maybe close the PR and solve it differently because if the view is not there is creates "hard" jump when hiding keyboard)

  • select #0 (when bottom sheet is smaller than keyboard)
  • hide keyboard
  • select #0 again (when bottom sheet is fully opened)

In this case, the onFocusedInputLayoutChanged is not called second time, because the focus input is the same. The problem is it still remembers the previous position of the input so it thinks it is behind the keyboard and it does the scrolling. Once I select #1 input and after 0 it gets the correct position on the screen.

  const inputLayoutHandler = useFocusedInputLayoutHandler(
    {
      onFocusedInputLayoutChanged: (e) => {
        "worklet";

        if (e.target !== -1) {
          layout.value = e;
        } else {
          layout.value = null;
        }
      },
    },
    [],
  );

What I think should happen is to check the current position of text input in all those functions maybeScroll, onStart, onMove, onEnd and based on that decide if we need to scroll. Because the absolute position of the text field is changing when keyboard is showing.

Another option would be to listen for the position of the current focused text field if possible and then check the current position in maybeScroll.

What do you think?

Repo for reproducing
I have this code setup where I use BottomSheet with BottomSheetTextInputs and this libraries' KeyboardAwareScrollView, which is just wrapped by createBottomSheetScrollableComponent.

      <KeyboardProvider>
        <BottomSheet
          ref={bottomSheetRef}
          onChange={handleSheetChanges}
          snapPoints={snapPoints}
          topInset={100}
        >
        <BottomSheetScrollView>
          {(new Array(15).fill(undefined)).map((_, index) => {
            return (
              <View key={index} style={{ backgroundColor: 'blue', margin: 8, borderBottomWidth: 2, paddingVertical: 16}}>
                <BottomSheetTextInput key={index} placeholder={`Input #${index}`} style={{ backgroundColor: 'yellow' }} />
              </View>
            )
          })}
        </BottomSheetScrollView>
        </BottomSheet>
      </KeyboardProvider>

To Reproduce
Explained above

Expected behavior
Well I think it should just do nothing actually :) Because TextInput will be eventually above the keyboard.

Screenshots
Uploaded above.

Smartphone (please complete the following information):

  • Desktop OS: [MacOS 15
  • Device: iPhone 16 pro simulator
  • OS: latest
  • RN version: 76
  • RN architecture: old
  • JS engine: jsc
  • Library version: latest

Please let me know if any questions. I appreciate the help.

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions