react-nativedropdowncss-positionreact-native-paperreact-native-stylesheet

Make a dropdown list to select in TextInput


Im using react-native-paper which is a great library, but i ran into a problem when i needed a dropdown menu, that is overlay on the TextInput field around it. Don't want to use any Library unless it it maintained properly.

  return (
    <View style={{ top: StatusBar.currentHeight }}>
      <View
        style={{
          flexDirection: 'row',
          justifyContent: 'space-around',
          marginVertical: 10,
        }}>
        <TextInput
          label={'Title'}
          placeholder={'Mr'}
          value={userinput}
          style={{ width: '30%' }}
          onChangeText={(text) => setUserinput(text)}
          right={<TextInput.Icon icon="chevron-down" size={20} />}
        />
        <TextInput label={'First name'} style={{ width: '60%' }} />
      </View>
      <View style={{ alignSelf: 'center', width: '95%' }}>
        <TextInput
          label={'Phone number'}
          onChangeText={(text) => setUserinput(text)}
        />
      </View>
    </View>
  );

Currently screenshot of the current state. Required: Required

Bare minimum Expo Snack code.

Already tried

  1. Although react-native-paper provides List & List.Accordion but my problem is not solving by that. issue When list is open the other text bot field are also extending there height.

  2. Mapping function, Flatlist, issue not getting the results that i want.

  3. Position: Absolute issue Mapping is not working accordingly.


Solution

  • I did it using flatlist with zIndex properties, check my example code

    Example:

    import React, { useState, useCallback } from 'react';
    import { View, StatusBar, FlatList, TouchableOpacity, Text, Keyboard } from 'react-native';
    import { TextInput } from 'react-native-paper';
        
        const App = () => {
          const [userinput, setUserinput] = useState(null);
          const [show, setShow] = useState(false);
          const openPicker = useCallback(
            () => {
              Keyboard.dismiss()
              setShow(true)
            },
            [show]
          );
        
          const hidePicker = useCallback(
            (item) => {
              setShow(false)
              setUserinput(item)
            },
            [show, userinput]
          );
        
          return (
            <View style={{ top: StatusBar.currentHeight }}>
              <View
                style={{
                  flexDirection: 'row',
                  justifyContent: 'space-around',
                  marginVertical: 10,
                }}>
                <View style={{ width: '30%' }}>
                  <TextInput
                    label={'Title'}
                    placeholder={show ?'' :'Mr'}
                    value={userinput}
                    style={{ width: '100%' }}
                    onChangeText={(text) => setUserinput(text)}
        
                    right={<TextInput.Icon onPress={openPicker} icon="chevron-down" size={20} />}
                  />
                  {show ?
                    <FlatList
                      style={{ backgroundColor: 'rgb(211, 211, 211)',elevation:1, zIndex: 22, width: '100%', marginTop: 60, position: 'absolute' }}
                      data={['Mr', 'Mrs', 'Miss']}
                      renderItem={({ item, index }) => (
                        <TouchableOpacity
                          onPress={() => hidePicker(item)}>
                          <Text style={{padding:8}}>
                            {item}
                          </Text>
                        </TouchableOpacity>
                      )}
                      keyExtractor={item => item}
                    />
                    : null}
                </View>
                <TextInput label={'First name'} style={{ width: '60%' }} />
              </View>
              <View style={{ alignSelf: 'center', width: '95%', zIndex: -1 }}>
                <TextInput
                  label={'Phone number'}
                  onChangeText={(text) => setUserinput(text)}
                />
              </View>
            </View>
          );
        };
        
        export default App;
    

    Note: marginTop will be the same as input height and you can also move the flatlist to components