HomeOur TeamContact

Picker Select

By Utkarsh Lubal
Published in UI
May 06, 2023
1 min read
Picker Select

Table Of Contents

01
Introduction
02
Installing
03
Example
04
Tutorial

Introduction

A Picker component for React Native which emulates the native <select> interfaces for iOS and Android

For iOS, by default we are wrapping an unstyled TextInput component. You can then pass down styles to customize it to your needs.

For Android, by default we are using the native Picker component. If you prefer, you can set useNativeAndroidPickerStyle to false, which will also render an unstyled TextInput component. You can then pass down styles to customize it to your needs.

For either platform, you can alternatively pass down a child element of your choice that will be wrapped in a touchable area.

Installing

npm install react-native-picker-select
React Native users
npm install @react-native-picker/picker
npx pod-install
Expo
expo install @react-native-picker/picker

Example

-import React from 'react';
import {
  Button,
  Text,
  TextInput,
  Platform,
  ScrollView,
  StyleSheet,
  TouchableWithoutFeedback,
  View,
} from 'react-native';
import { Chevron } from 'react-native-shapes';
import { Ionicons } from '@expo/vector-icons';
import RNPickerSelect, { defaultStyles } from 'react-native-picker-select';
// import RNPickerSelect, { defaultStyles } from './debug';

const sports = [
  {
    label: 'Football',
    value: 'football',
  },
  {
    label: 'Baseball',
    value: 'baseball',
  },
  {
    label: 'Hockey',
    value: 'hockey',
  },
];

export default class App extends React.Component {
  constructor(props) {
    super(props);

    this.inputRefs = {
      firstTextInput: null,
      favSport0: null,
      favSport1: null,
      lastTextInput: null,
      favSport5: null,
    };

    this.state = {
      numbers: [
        {
          label: '1',
          value: 1,
          color: 'orange',
        },
        {
          label: '2',
          value: 2,
          color: 'green',
        },
      ],
      favSport0: undefined,
      favSport1: undefined,
      favSport2: undefined,
      favSport3: undefined,
      favSport4: 'baseball',
      previousFavSport5: undefined,
      favSport5: null,
      favNumber: undefined,
    };

    this.InputAccessoryView = this.InputAccessoryView.bind(this);
  }

  InputAccessoryView() {
    return (
      <View style={defaultStyles.modalViewMiddle}>
        <TouchableWithoutFeedback
          onPress={() => {
            this.setState(
              {
                favSport5: this.state.previousFavSport5,
              },
              () => {
                this.inputRefs.favSport5.togglePicker(true);
              }
            );
          }}
          hitSlop={{ top: 4, right: 4, bottom: 4, left: 4 }}>
          <View testID="needed_for_touchable">
            <Text
              style={[
                defaultStyles.done,
                { fontWeight: 'normal', color: 'red' },
              ]}>
              Cancel
            </Text>
          </View>
        </TouchableWithoutFeedback>
        <Text>Name | Prefer</Text>
        <TouchableWithoutFeedback
          onPress={() => {
            this.inputRefs.favSport5.togglePicker(true);
          }}
          hitSlop={{ top: 4, right: 4, bottom: 4, left: 4 }}>
          <View testID="needed_for_touchable">
            <Text style={defaultStyles.done}>Done</Text>
          </View>
        </TouchableWithoutFeedback>
      </View>
    );
  }

  render() {
    const placeholder = {
      label: 'Select a sport...',
      value: null,
      color: '#9EA0A4',
    };

    return (
      <View style={styles.container}>
        <ScrollView
          style={styles.scrollContainer}
          contentContainerStyle={styles.scrollContentContainer}>
          <Text>Standard TextInput</Text>
          <TextInput
            ref={el => {
              this.inputRefs.firstTextInput = el;
            }}
            returnKeyType="next"
            enablesReturnKeyAutomatically
            onSubmitEditing={() => {
              this.inputRefs.favSport0.togglePicker();
            }}
            style={
              Platform.OS === 'ios'
                ? pickerSelectStyles.inputIOS
                : pickerSelectStyles.inputAndroid
            }
            blurOnSubmit={false}
          />

          <View paddingVertical={5} />

          <Text>useNativeAndroidPickerStyle (default)</Text>
          {/* and iOS onUpArrow/onDownArrow toggle example */}
          <RNPickerSelect
            placeholder={placeholder}
            items={sports}
            onValueChange={value => {
              this.setState({
                favSport0: value,
              });
            }}
            onUpArrow={() => {
              this.inputRefs.firstTextInput.focus();
            }}
            onDownArrow={() => {
              this.inputRefs.favSport1.togglePicker();
            }}
            style={pickerSelectStyles}
            value={this.state.favSport0}
            ref={el => {
              this.inputRefs.favSport0 = el;
            }}
          />

          <View paddingVertical={5} />

          <Text>set useNativeAndroidPickerStyle to false</Text>
          <RNPickerSelect
            placeholder={placeholder}
            items={sports}
            onValueChange={value => {
              this.setState({
                favSport1: value,
              });
            }}
            style={pickerSelectStyles}
            value={this.state.favSport1}
            useNativeAndroidPickerStyle={false}
            ref={el => {
              this.inputRefs.favSport1 = el;
            }}
          />

          <View paddingVertical={5} />

          <Text>set placeholder to empty object</Text>
          {/* and hiding the InputAccessoryView on iOS */}
          <RNPickerSelect
            placeholder={{}}
            items={sports}
            onValueChange={value => {
              this.setState({
                favSport2: value,
              });
            }}
            InputAccessoryView={() => null}
            style={pickerSelectStyles}
            value={this.state.favSport2}
          />

          <View paddingVertical={5} />

          <Text>custom icon using react-native-shapes</Text>
          {/* and useNativeAndroidPickerStyle={false} with underlineColorAndroid */}
          <RNPickerSelect
            placeholder={placeholder}
            items={sports}
            onValueChange={value => {
              this.setState({
                favSport3: value,
              });
            }}
            style={{
              inputAndroid: {
                backgroundColor: 'transparent',
              },
              iconContainer: {
                top: 5,
                right: 15,
              },
            }}
            value={this.state.favSport3}
            useNativeAndroidPickerStyle={false}
            textInputProps={{ underlineColorAndroid: 'cyan' }}
            Icon={() => {
              return <Chevron size={1.5} color="gray" />;
            }}
          />

          <View paddingVertical={5} />

          <Text>custom icon using react-native-vector-icons</Text>
          {/* and value defined */}
          <RNPickerSelect
            placeholder={placeholder}
            items={sports}
            onValueChange={value => {
              this.setState({
                favSport4: value,
              });
            }}
            style={{
              ...pickerSelectStyles,
              iconContainer: {
                top: 10,
                right: 12,
              },
            }}
            value={this.state.favSport4}
            useNativeAndroidPickerStyle={false}
            textInputProps={{ underlineColor: 'yellow' }}
            Icon={() => {
              return <Ionicons name="md-arrow-down" size={24} color="gray" />;
            }}
          />

          <View paddingVertical={5} />

          <Text>custom icon using your own css</Text>
          {/* and placeholder style changes, showing colors on items, useNativeAndroidPickerStyle={false} */}
          <RNPickerSelect
            placeholder={{
              label: 'Select a number or add another...',
              value: null,
              color: 'red',
            }}
            items={this.state.numbers}
            onValueChange={value => {
              this.setState({
                favNumber: value,
              });
            }}
            style={{
              ...pickerSelectStyles,
              iconContainer: {
                top: 20,
                right: 10,
              },
              placeholder: {
                color: 'purple',
                fontSize: 12,
                fontWeight: 'bold',
              },
            }}
            value={this.state.favNumber}
            Icon={() => {
              return (
                <View
                  style={{
                    backgroundColor: 'transparent',
                    borderTopWidth: 10,
                    borderTopColor: 'gray',
                    borderRightWidth: 10,
                    borderRightColor: 'transparent',
                    borderLeftWidth: 10,
                    borderLeftColor: 'transparent',
                    width: 0,
                    height: 0,
                  }}
                />
              );
            }}
          />
          <Button
            title="+1 number to the above list"
            onPress={() => {
              const { numbers } = this.state;
              const value = numbers.length + 1;
              numbers.push({
                label: `${value}`,
                value,
                color: 'dodgerblue',
              });
              this.setState({
                numbers,
              });
            }}
          />

          <View paddingVertical={5} />

          <Text>custom InputAccessoryView on iOS</Text>
          <RNPickerSelect
            items={sports}
            value={this.state.favSport5}
            onValueChange={value => {
              this.setState({
                favSport5: value,
              });
            }}
            onOpen={() => {
              this.setState({
                previousFavSport5: this.state.favSport5,
              });
            }}
            InputAccessoryView={this.InputAccessoryView}
            ref={ref => {
              this.inputRefs.favSport5 = ref;
            }}
          />
        </ScrollView>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  scrollContainer: {
    flex: 1,
    paddingHorizontal: 15,
  },
  scrollContentContainer: {
    paddingTop: 40,
    paddingBottom: 10,
  },
});

const pickerSelectStyles = StyleSheet.create({
  inputIOS: {
    fontSize: 16,
    paddingVertical: 12,
    paddingHorizontal: 10,
    borderWidth: 1,
    borderColor: 'gray',
    borderRadius: 4,
    color: 'black',
    paddingRight: 30, // to ensure the text is never behind the icon
  },
  inputAndroid: {
    fontSize: 16,
    paddingHorizontal: 10,
    paddingVertical: 8,
    borderWidth: 0.5,
    borderColor: 'purple',
    borderRadius: 8,
    color: 'black',
    paddingRight: 30, // to ensure the text is never behind the icon
  },
});

Tutorial

Coming Soon…


Previous Article
Pinch Gesture recognizers
Next Article
Parallax Swiper
Utkarsh Lubal

Utkarsh Lubal

Full Stack Developer

Related Posts

Vertical Step indicator
Vertical Step indicator
May 06, 2023
1 min

Quick Links

Advertise with usAbout UsContact Us

Social Media