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.54k stars 61 forks source link

Support `KeyboardAwareScrollView` with FlatList imported from `react-native-gesture-handler` #505

Closed thisisgit closed 1 month ago

thisisgit commented 1 month ago

Is your feature request related to a problem? Please describe. Hi first of all, thanks for making this awesome library.

I just installed and tried it out and it works great with FlatList from react-native. But found out that it doesn't work with FlatList imported from react-native-gesture-handler. It doesn't avoid the keyboard when TextInput is focused. I'm considering to use FlatList from RN gesture handler to support gesture composition

Is there any workaround to use it with RN gesture handler's FlatList?

kirillzyusko commented 1 month ago

@thisisgit can you post a code example that you are using?

thisisgit commented 1 month ago

Hi @kirillzyusko, here's sample code:

import { StyleSheet, FlatList, ListRenderItemInfo } from 'react-native';
import {
  FlatList as RNGHFlatList,
  TextInput,
} from 'react-native-gesture-handler';
import React, { useCallback } from 'react';
import { KeyboardAwareScrollView } from 'react-native-keyboard-controller';

type ListItem = {
  id: string;
  text: string;
};

const DATA: ListItem[] = [
  {
    id: '1',
    text: 'Test1',
  },
  {
    id: '2',
    text: 'Test2',
  },
  {
    id: '3',
    text: 'Test3',
  },
  {
    id: '4',
    text: 'Test4',
  },
  {
    id: '5',
    text: 'Test5',
  },
  {
    id: '6',
    text: 'Test6',
  },
  {
    id: '7',
    text: 'Test7',
  },
];

export const TestKeyboardAwareList = () => {
  const renderItem = useCallback(({ item }: ListRenderItemInfo<ListItem>) => {
    return <TextInput style={styles.input} value={item.text} />;
  }, []);

  return (
    <RNGHFlatList
      data={DATA}
      renderItem={renderItem}
      keyExtractor={(item) => item.id}
      keyboardDismissMode={'interactive'}
      renderScrollComponent={(props) => {
        return <KeyboardAwareScrollView {...props} />;
      }}
    />
  );
};

const styles = StyleSheet.create({
  input: {
    height: 80,
    borderWidth: 1,
    width: '100%',
  },
});

And this is what it looks like:

https://github.com/kirillzyusko/react-native-keyboard-controller/assets/13231564/c369846e-7df7-4b22-a88a-7d0086d4269a

If I replace RNGHFlatList with FlatList, it works fine:

https://github.com/kirillzyusko/react-native-keyboard-controller/assets/13231564/0cd78d09-c478-4473-9961-f25f5b0174e4

kirillzyusko commented 1 month ago

@thisisgit the code snippet above doesn't work, because GH overwrite renderScrollComponent with their own implementation: https://github.com/software-mansion/react-native-gesture-handler/blob/f0dfef28b2de2b2ec479f86732120b2bf2c2506b/src/components/GestureComponents.tsx#L119-L127

I'll think about on how to handle that πŸ‘

kirillzyusko commented 1 month ago

An off-topic question - do you have an example on how to integrate FlashList + ScrollView from GestureHandler?

thisisgit commented 1 month ago

@thisisgit the code snippet above doesn't work, because GH overwrite renderScrollComponent with their own implementation: https://github.com/software-mansion/react-native-gesture-handler/blob/f0dfef28b2de2b2ec479f86732120b2bf2c2506b/src/components/GestureComponents.tsx#L119-L127

I'll think about on how to handle that πŸ‘

Well I think then you don't have to support FlatList from RNGH since what they're doing is to use FlatList from RN and use their ScrollView to render scroll component. I can see that your KeyboardAwareScrollView is already using ScrollView component of reanimated so I think it shouldn't be an issue on working with gesture composition?

I created an issue in RNGH to remove that prop

An off-topic question - do you have an example on how to integrate FlashList + ScrollView from GestureHandler?

Can you elaborate on what you mean by "integrate" FlashList + ScrollView? Are you trying to achieve gesture composition with FlashList? If it's about gesture composition, I followed this example

TMI: I moved away from FlashList like 2 weeks ago since it didn't work well with TextInputs due to its recycling behavior. e.g. Focusing TextInput at index 50 and scrolling up will change its focus to TextInput at lower index(<50) since they're being recycled.

thisisgit commented 1 month ago

I'll close this since the issue is coming from RNGH.

kirillzyusko commented 1 month ago

I can see that your KeyboardAwareScrollView is already using ScrollView component of reanimated so I think it shouldn't be an issue on working with gesture composition?

The small problem here is that Reanimated.ScrollView takes ScrollView from react-native, but react-native-gestire-handler exports its own version. Ideally the integration should look like:

import {ScrollView} from 'react-native-gesture-handler';
import Reanimated from 'react-native-reanimated';

const scrollViewComponent = Reanimated.createAnimatedComponent(ScrollView);

<FlatList
  renderScrollComponent={(props) => <KeyboardAwareScrollView {...props} scrollViewComponent={scrollViewComponent} />}
/>

The current implementation of KeyboardAwareScrollView doesn't support custom scrollables, but you can patch the package temporarily to see whether such idea will work or not πŸ‘€

And if such code will work, then I would be happy to re-open that issue and merge a PR to allow custom scrollables πŸ‘

Can you elaborate on what you mean by "integrate" FlashList + ScrollView? Are you trying to achieve gesture composition with FlashList? If it's about gesture composition, I followed https://github.com/software-mansion/react-native-gesture-handler/issues/2175#issuecomment-1230207219

Yes, I meant this πŸ™‚

thisisgit commented 1 month ago

@kirillzyusko I see. I'll give you a feedback once I test them out. I'm not working on gesture composition yet but will probably try them out after urgent tasks are smashed.

Hope the example link I shared helped. Thanks for the hardworksπŸ’ͺ