简体   繁体   中英

How to make a custom Radio Button with animation? React Native

I've made a custom Radio Button in React Native. Below is the link to my code.

https://gist.github.com/shubh007-dev/0d8a0ca4d6f7d1530f3e28d223f9199e

What I want is to animate the radio button when I press it, like it's done in this library - https://www.npmjs.com/package/react-native-simple-radio-button

I'm able to animate my radio button for the first time but when I press another radio button, animation doesn't happen.

(Another approach for this question) How can I make sure that the Animated value is different for each Radio Button?

You either have to make a custom component for the radio or use x animated variable for x radio buttons.

Now, making x variable for x buttons is not an efficient solution but it could be used if you got only a few buttons.

You made a custom component which renders a flatlist and that's the problem; can't animate buttons separately in the same component you use to render them.

You should split your code and make the radio button a component itself. Something like that (didn't test it, but that way it should work) :

export class RadioButton extends Component {
  constructor(props) {
    super(props);
    this.state = {
      radioSelected: this.props.selectedItemId,
    };
  }

  radioClick = id => {
    this.setState({ radioSelected: id });
    this.props.onChange(id);
  }

  renderRadioButton = item => {
    const { radioSelected } = this.state;
    const { labelLeftStyle, labelRightStyle, labelOnRight } = this.props;
    return (
      <AnimatedRadio
        {...item}
        isSelected={item.id === radioSelected}
        labelLeftStyle={labelLeftStyle}
        labelRightStyle={labelRightStyle}
        labelOnRight={labelOnRight}
        radioClick={this.radioClick}
      />
    );
  };

  render() {
    return (
      <FlatList
        data={this.props.radioOptions}
        extraData={this.state}
        renderItem={({ item }) => this.renderRadioButton(item)}
        keyExtractor={(item, index) => index.toString()}
      />
    );
  }
}

export class AnimatedRadio extends Component {
  springValue = new Animated.Value(1.1);

  onRadioClick = id => () => {
    const { radioClick } = this.props;
    radioClick(id);
    this.spring();
  };

  spring = () => {
    Animated.spring(this.springValue, {
      toValue: 0.95,
      friction: 2,
      tension: 15,
    }).start();
  };

  render() {
    const {
      id,
      label,
      labelLeftStyle,
      labelRightStyle,
      labelOnRight,
      isSelected,
    } = this.props;
    return (
      <View key={id} style={STYLES.radioContainerView}>
        <TouchableOpacity
          style={STYLES.radioButtonDirectionStyle}
          onPress={this.onRadioClick(id)}
        >
          {labelOnLeft == true ? (
            <Text style={[labelLeftStyle]}>{label}</Text>
          ) : null}

          <View
            style={[isSelected ? STYLES.selectedView : STYLES.unselectedView]}
          >
            {isSelected ? (
              <Animated.View
                style={[
                  STYLES.radioSelected,
                  { transform: [{ scale: this.springValue }] },
                ]}
              />
            ) : null}
          </View>

          {labelOnRight == true ? (
            <Text style={[labelRightStyle]}>{label}</Text>
          ) : null}
        </TouchableOpacity>
      </View>
    );
  }
}

This way each component radio will have its own animated value, and won't interfere with others buttons.

I did it using LayoutAnimation like below.

LayoutAnimation.configureNext({
              duration: 300,
              create: {
                type: 'linear',
                property: 'scaleXY',
              },
              update: {
                type: 'spring',
                springDamping: 0.4,
                property: 'opacity',
              },
              delete: {
                type: 'easeOut',
                property: 'opacity',
              },
            });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM