Skip to content
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

Patch keyboard overlap and nested scroll bugs #1

Merged
merged 1 commit into from
Feb 6, 2024

Conversation

CarterSimonson
Copy link
Owner

@CarterSimonson CarterSimonson commented Feb 6, 2024

Intro

This PR patches a couple of bugs that I've run into with the react-native-draggable-flatlist package.

Use case and demo

I'm building a recipe editor UI with a feature for drag-and-drop reordering ingredients and instructions.

demo.mov

Bugs patched

Scroll is broken in NestableScrollContainer

There's an open issue in the repo for this -> computerjazz#497

The workaround that I was able to find is:

  • Update the PanHandler in DraggableFlatList to utilize an enabled state.
    • Set the pan handler to "manual activation" mode
  • Compose a simultaneous tapGesture that replaces the "drag" function returned to list items
    • Set the shared enabled state to true when the tapGesture is pressed down.
    • Reset enabled to false on press up.

I initially tried controlling the enabled state from within the drag function but was getting some gnarly race conditions.

This results in the following behavior:

  • If the user attempts to drag without triggering the tapGesture, the panGesture will fail and allow the regular scroll event.
  • If the user drags on the tappable area (the drag icon for me in this case), the tapGesture will fire simultaneously and set the enabled state to true. The panGesture will activate and track the pan events.

Here's what that looks like within the consuming application:

  // The `drag` handler has been replaced by `tapGesture`
  function renderItem({ item, getIndex, tapGesture }: RenderItemParams<KeyedString>) {
    const index = getIndex();

    const right = (
      <GestureDetector gesture={tapGesture}>
        <DragIcon />
      </GestureDetector>
    );

    if (index !== undefined) {
      return (
        <InputListItem
          value={item.value}
          onChangeText={(value) => updateIngredient(value, index)}
          onBlur={() => onBlur(index)}
          right={right}
        />
      );
    }
  }

Inputs are not keyboard aware

I found that neither react-native-keyboard-aware-scroll-view or KeyboardAvoidingView were compatible with the NestableScrollContainer.

This is worked around by the useKeyboardListener hook that is introduced in this PR. It listens to keyboard events and automatically scrolls to prevent the input from being hidden. Note that this only seemed to be necessary on iOS.

@AppDeveloperGroup
Copy link

Thank you very much, but on iOS when using onTouchesDown and onTouchesUp the application crashed, the solution that worked for me is const tapGesture = Gesture.Tap()
.onBegin(() => {
enabled.value = true;
runOnJS(drag)();
})
.onEnd(() => {
enabled.value = false;
})
.simultaneousWithExternalGesture(panGesture); works both on iOS and Android, and also if you use TextInput multiline={true} when increasing the size, the new text is hidden under the keyboard

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants