Как сделать пользовательскую радиокнопку с анимацией? Реагировать на родной

Я сделал собственную радиокнопку в React Native. Ниже ссылка на мой код.

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

Что я хочу, так это анимировать переключатель, когда я нажимаю его, как это делается в этой библиотеке - https://www.npmjs.com/package/react-native-simple-radio-button

Я могу анимировать свой переключатель в первый раз, но когда я нажимаю другой переключатель, анимация не происходит.

(Еще один подход к этому вопросу) Как я могу убедиться, что значение Animated отличается для каждого переключателя?


person Shubham Bisht    schedule 25.06.2019    source источник


Ответы (2)


Вам нужно либо создать пользовательский компонент для радио, либо использовать x анимированную переменную для x переключателей.

Теперь создание переменной x для кнопок x не является эффективным решением, но его можно использовать, если у вас всего несколько кнопок.

Вы создали собственный компонент, который отображает плоский список, и в этом проблема; нельзя анимировать кнопки отдельно в том же компоненте, который вы используете для их рендеринга.

Вы должны разделить свой код и сделать переключатель самим компонентом. Что-то вроде этого (не проверял, но так должно работать):

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>
    );
  }
}

Таким образом, каждое радио компонента будет иметь собственное анимированное значение и не будет мешать другим кнопкам.

person Fakebounce    schedule 25.06.2019
comment
но не будет ли плохим решением использовать анимированную переменную x для переключателей x? И я сделал пользовательский компонент здесь. Возможно ли, если бы вы могли порекомендовать какое-либо другое решение? :) - person Shubham Bisht; 26.06.2019
comment
Я просто перечислял ваши решения, не говоря, хороший это или плохой подход. Я обновлю свой ответ компонентом - person Fakebounce; 26.06.2019
comment
Да, пожалуйста. Спасибо. :) - person Shubham Bisht; 26.06.2019
comment
Я обновил код, я забыл поведение функции radioClick. Теперь у вас должно получиться что-то функциональное. - person Fakebounce; 26.06.2019
comment
Это дает мне ошибку, undefined не является объектом (оценка «this.setState») - person Shubham Bisht; 26.06.2019
comment
Я не привязывал radioClick к первому компоненту, теперь должно работать. я обновил код - person Fakebounce; 26.06.2019
comment
Я это сделал. Проверьте мой ответ. - person Shubham Bisht; 26.06.2019

Я сделал это, используя LayoutAnimation, как показано ниже.

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