ArnaudRinquin / react-native-radio-buttons

[DEPRECATED] A Radio-button like logic wrapper for React Native
https://www.npmjs.com/package/react-native-radio-buttons
MIT License
413 stars 97 forks source link
radio-buttons react-native

react-native-radio-buttons

IMPORTANT this package is deprecated and no longer maintained in favor of the official SegmentedControlIOS component.

A react component to implement radio buttons-like behaviors: multiple options, only one option can be selected at a given time.

Both the container and option nodes are customizable. Comes with SegmentedControls clone, only more customizable (see below, animations to come).

example

Install

npm i -S react-native-radio-buttons

Demo app

git clone https://github.com/ArnaudRinquin/react-native-radio-buttons.git
cd react-native-radio-buttons
npm run demo

Usage

Here is an extensive overview of the component usage.

import { RadioButtons } from 'react-native-radio-buttons'

// ...

render() {
  const options = [
    "Option 1",
    "Option 2"
  ];

  function setSelectedOption(selectedOption){
    this.setState({
      selectedOption
    });
  }

  function renderOption(option, selected, onSelect, index){
    const style = selected ? { fontWeight: 'bold'} : {};

    return (
      <TouchableWithoutFeedback onPress={onSelect} key={index}>
        <Text style={style}>{option}</Text>
      </TouchableWithoutFeedback>
    );
  }

  function renderContainer(optionNodes){
    return <View>{optionNodes}</View>;
  }

  return (
    <View style={{margin: 20}}>
      <RadioButtons
        options={ options }
        onSelection={ setSelectedOption.bind(this) }
        selectedOption={this.state.selectedOption }
        renderOption={ renderOption }
        renderContainer={ renderContainer }
      />
      <Text>Selected option: {this.state.selectedOption || 'none'}</Text>
    </View>);
}

Will render this

Example

Props

Full JavaScript SegmentedControls clone

This library comes with a clone of the native SegmentedControls, based on RadioButtons.

import { SegmentedControls } from 'react-native-radio-buttons'

// ...

<SegmentedControls
  options={ options }
  onSelection={ setSelectedOption.bind(this) }
  selectedOption={ this.state.selectedOption }
/>

You override all the defaults through the props.

<SegmentedControls
  tint={'#f80046'}
  selectedTint= {'white'}
  backTint= {'#1e2126'}
  options={ options }
  allowFontScaling={ false } // default: true
  onSelection={ setSelectedOption.bind(this) }
  selectedOption={ this.state.selectedOption }
  optionStyle={{fontFamily: 'AvenirNext-Medium'}}
  optionContainerStyle={{flex: 1}}
/>

Here is the list of the props you might override:

const IOS_BLUE = '#007AFF';
const IOS_WHITE = '#ffffff';

const DEFAULTS = {
  direction: 'row',

  tint: IOS_BLUE,
  backTint: IOS_WHITE,

  paddingTop: 5,
  paddingBottom: 5,
  textAlign: 'center',

  selectedTint: IOS_WHITE,
  selectedBackgroundColor: IOS_WHITE,

  separatorTint: IOS_BLUE,
  separatorWidth: 1,

  containerBorderTint: IOS_BLUE,
  containerBorderWidth: 1,
  containerBorderRadius: 5,

}

You can also specify containerStyle, optionContainerStyle, and optionStyle to use any style you want:

You can also specify how to extract the labels from the options through the extractText prop.

options = [
  {
    label: 'Option 1',
    value: 'opt1'
  },
  {
    label: 'Option 2',
    value: 'opt2'
  }
]

<SegmentedControls
  options={ options }
  onSelection={ setSelectedOption.bind(this) }
  selectedOption={ this.state.selectedOption }
  extractText={ (option) => option.label }
/>

If you decide to declare options as an array of objects, do also include a testOptionEqual prop for customized equality checking, otherwise changing selectedOption programmatically would not update the UI correctly.

With the above options, you'll need testOptionEqual to be as follows in order for selectedOption to display correctly.

  <SegmentedControls
    options={ options }
    onSelection={ setSelectedOption.bind(this) }
    selectedOption={ this.state.selectedOption }
    extractText={ (option) => option.label }
    testOptionEqual={(selectedValue, option) => selectedValue === option.value}
  />

Moreover, you can even specify the whole renderOption() function:

<SegmentedControls
  // ...
  renderOption={(option, selected) => {
    return (
      // ...render stuff
    )
  }}
}}

Helpers

RadioButtons.renderVerticalContainer;

A super simple renderContainer function that generates a with {flexDirection: "column"}. It is used as default renderContainer if you don't specify it.

Usage:

<RadioButtons
  options={ options }
  onSelection={ setSelectedOption }
  renderContainer={RadioButtons.renderVerticalContainer}
/>

RadioButtons.renderHorizontalContainer;

Another super simple renderContainer function that generates a with {flexDirection: "row"}

Usage:

<RadioButtons
  options={ options }
  onSelection={ setSelectedOption }
  renderContainer={RadioButtons.renderHorizontalContainer}
/>

RadioButtons.getViewContainerRenderer(viewContainerStyle);

An helper that generates a simple <View> with the provided style.

Usage:

<RadioButtons
  options={ options }
  onSelection={ setSelectedOption }
  renderContainer={RadioButtons.getViewContainerRenderer({
    backgroundColor: '#f80046',
    flexDirection: 'row',
    justifyContent: 'space-around',
  })}
/>

RadioButtons.getTextOptionRenderer(normalStyle, selectedStyle, extractText);

An helper that generates <Text> options wrapped in <TouchableWithoutFeedback>. normalStyle and selectedStyle will be applied to the nodes, depending on state. extractText(options) can be specified.

Usage:

const normalStyle = {
  color: 'white'
};

const selectedStyle = {
  color: '#f80046',
  fontWeight: 'bold'
};

const extractText = (option) => option.label;

<RadioButtons
  options={ options }
  onSelection={ setSelectedOption }
  renderOptions={RadioButtons.getTextOptionRenderer(normalStyle, selectedStyle, extractText)}
/>