dabakovich / react-native-controlled-mentions

Fully controlled React Native mentions component
MIT License
222 stars 82 forks source link

renderSuggestions scrolling not working in android #113

Open kashee-lv opened 1 year ago

kashee-lv commented 1 year ago

Hi I want to scroll the suggestion list but i am facing issue with android and its working in ios, below is my code for renderSuggestions function

` const renderSuggestions = ({keyword, onSuggestionPress}) => { if ( keyword === null || keyword === undefined || mappedMembers.length === 0 ) { return null; } const suggestionArrayToRender = mappedMembers.filter(item => item.name.toLowerCase().includes(keyword.toLowerCase()), );

return (
  <View
    style={{
      // backgroundColor: 'red',
      width: 200,
      borderColor: 'gray',
      borderWidth: 0.5,
      opacity: 1,
    }}>
    <ScrollView nestedScrollEnabled style={{flexGrow: 1, height: 200}}>
      {suggestionArrayToRender
        .filter(item =>
          item.name.toLowerCase().includes(keyword.toLowerCase()),
        )
        .map(one => (
          <Pressable
            key={one.id}
            onPress={() => onSuggestionPress(one)}
            style={{padding: 12}}>
            <Text style={{color: COLORS.textBlack}}>{one.name}</Text>
          </Pressable>
        ))}
    </ScrollView>
  </View>
);

} `

MariusCatanoiu commented 1 year ago

I have the same issue

fukemy commented 1 year ago

any solution?

kashee-lv commented 1 year ago

@fukemy not yet please let me know if you find any thing.

fukemy commented 1 year ago

could you try to use ScrollView from 'react-native-gesture-handler'?

kashee-lv commented 1 year ago

@fukemy no i am using ScrollView from react-native.

MariusCatanoiu commented 1 year ago

@fukemy I tried it a month ago. Same thing

fukemy commented 1 year ago

ok i will give my solution

kashee-lv commented 1 year ago

@fukemy how you plugin your MentionView function with <MentionInput/>

fukemy commented 1 year ago

@fukemy how you plugin your MentionView function with <MentionInput/>

I am using ref to share the trigger data between MentionView and InputView

kashee-lv commented 1 year ago

@fukemy how you plugin your MentionView function with <MentionInput/>

I am using ref to share the trigger data between MentionView and InputView

I hope you don't mind to share the code snippet, please

kashee-lv commented 1 year ago

@fukemy I tried to implement as you shared the code but i am facing some issues,

  1. its not filtering the list data as i am typing in TextInput
  2. List is rendering between the UI, I am expecting it should be appear as model

Simulator Screen Shot - iPhone 14 - 2023-04-29 at 18 50 58

Simulator Screen Shot - iPhone 14 - 2023-04-29 at 19 00 18

Choyeongdeok commented 1 year ago

I solved it by using FlatList from react-native-gesture-handler. when I used FlatList from react-native with position: 'absolute', the scroll doesn't work.

MariusCatanoiu commented 1 year ago

I solved it by using FlatList from react-native-gesture-handler. when I used FlatList from react-native with position: 'absolute', the scroll doesn't work.

I tried it some time ago, is not working for me.

yessinej commented 1 year ago

any update about this topic ?

Choyeongdeok commented 1 year ago

my code using FlatList from react-native-gesture-handler

    const renderSuggestions = ({ keyword = null, onSuggestionPress }) => {
        if(keyword === null) return null

        return (
            <View
                style={{
                    position: 'absolute',
                    bottom: inputHeight + 10,
                    width: deviceWidth,
                    left: -13,
                }}
            >
                <Shadow // react-native-shadow-2
                    startColor='rgba(0, 0, 0, 0.05)'
                    corners={{
                        topStart: true,
                        topEnd: true
                    }}
                    distance={12}
                    sides={{
                        top: true,
                        bottom: false
                    }}
                >
                <FlatList // react-native-gesture-handler
                    data={suggestions.filter(member => member?.name?.toLocaleLowerCase()?.includes(keyword?.toLocaleLowerCase()))}
                    renderItem={({ item }) => renderItem({ item, keyword, onSuggestionPress })}
                    keyboardShouldPersistTaps='always'
                    ListFooterComponent={() => (
                        <View style={{ height: 12 }}/>
                    )}
                    style={{
                        maxHeight: 230,
                        backgroundColor: '#FFFFFF',
                        borderTopRightRadius: 16,
                        borderTopLeftRadius: 16,
                        borderWidth: 1,
                        borderColor: '#E9E9E9',
                    }}
                />
            </Shadow>
            </View>
        )
    }

https://github.com/dabakovich/react-native-controlled-mentions/assets/54658590/64680737-905e-4d78-b782-4f11dab5cfa6

kashee-lv commented 1 year ago

It works well when you use it out side of the Flatlist, but problem happens when you use it over the scrollView

dabakovich commented 1 year ago

Hey all!

Thanks for using the library and providing your feedbacks.

I've also encountered this problem in my projects. The most compromising solution was using the Portal pattern. You can use this component from the react-native-paper library, from a separate library @gorhom/portal, or you can implement this component yourself.

Here is a very basic and simplified example that I used in production:

import * as React from 'react';
import { FC, useRef, useState } from 'react';
import { FlatList, Pressable, Text, TextInput, View } from 'react-native';
import {
  Suggestion,
  SuggestionsProvidedProps,
  TriggersConfig,
  useMentions,
} from 'react-native-controlled-mentions/dist';
import { Portal, PortalProvider } from '@gorhom/portal';
import { hashtags, messages } from './constants';

// Custom component for rendering suggestions
const Suggestions: FC<
  SuggestionsProvidedProps & { suggestions: Suggestion[]; inputHeight: number }
> = ({ keyword, onSelect, suggestions, inputHeight }) => {
  if (keyword == null) {
    return null;
  }

  return (
    <Portal>
      <View
        style={{
          position: 'absolute',
          width: '100%',
          maxHeight: 200,
          padding: 12,
          bottom: inputHeight,
        }}>
        <FlatList
          style={{
            backgroundColor: 'white',
            borderRadius: 12,
            borderWidth: 1,
            borderColor: 'grey',
          }}
          data={suggestions.filter(one =>
            one.name.toLocaleLowerCase().includes(keyword.toLocaleLowerCase()),
          )}
          renderItem={({ item }) => (
            <Pressable
              key={item.id}
              onPress={() => onSelect(item)}
              style={{ padding: 12 }}>
              <Text>{item.name}</Text>
            </Pressable>
          )}
          keyExtractor={item => item.id.toString()}
          keyboardShouldPersistTaps="handled"
        />
      </View>
    </Portal>
  );
};

// Config of suggestible triggers
const triggersConfig: TriggersConfig<'hashtag'> = {
  hashtag: {
    trigger: '#',
    textStyle: {
      fontWeight: 'bold',
      color: 'grey',
    },
  },
};

const MentionsFunctionalComponent = () => {
  const textInput = useRef<TextInput>(null);

  const [inputHeight, setInputHeight] = useState(0);

  const [textValue, setTextValue] = useState('Hello Mary! How are you?');

  const { textInputProps, triggers, mentionState } = useMentions({
    value: textValue,
    onChange: setTextValue,

    triggersConfig,
  });

  return (
    <PortalProvider>
      <View style={{ flex: 1, justifyContent: 'flex-end' }}>
        <FlatList
          data={messages}
          renderItem={({ item }) => (
            <Text style={{ padding: 10 }}>{item.text}</Text>
          )}
          keyExtractor={item => item.id.toString()}
        />

        <Suggestions
          suggestions={hashtags}
          {...triggers.hashtag}
          inputHeight={inputHeight}
        />

        <TextInput
          ref={textInput}
          multiline
          onLayout={event => {
            setInputHeight(event.nativeEvent.layout.height);
          }}
          placeholder="Type here..."
          style={{ padding: 12 }}
          {...textInputProps}
        />
      </View>
    </PortalProvider>
  );
};

export { MentionsFunctionalComponent };

Please note that for iOS there's no need to use Portal as scrolling together with position: 'absolute' works fine. Thus, you can use the following selector for root component in Suggestions:

const Component = Platform.OS === 'ios' ? Fragment : Portal;