Как обрабатывать анимацию на отдельных значках, отображаемых динамически? - PullRequest
0 голосов
/ 25 октября 2019

Сводка

У меня есть значок экспозиции в виде стрелки в заголовке аккордеона, который я пытаюсь анимировать, чтобы перевернуть на 180 градусов при нажатии, чтобы пользователь знал, что можетбыть закрытым или открытым. Эти заголовки отображаются динамически;Я не знаю, сколько будет входить, поскольку оно основано на том, сколько объектов пользователь открыл в другом программном обеспечении через API веб-сокетов.

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

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

То, что я пытался

Я пытался подражать этому подходу: Реагировать на родной: только анимация одного из нескольких элементов

Кажется, это немного отличается от моей проблемы (они работают только с размером шрифта), поэтому я не смог успешно применить это решение к своему коду.

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

Состояние содержит значение анимации


    this.state={
      activeSections: [],
      animValue: new Animated.Value(250),
    }

  }

Эта функция вызывается при нажатии заголовка.

  handleSelect = () => {
    this.state.animValue._value > 250
      ? Animated.timing(this.state.animValue, {
          toValue: 250,
          duration: 500
        }).start()
      : Animated.timing(this.state.animValue, {
          toValue: 450,
          duration: 500
        }).start();
  };

Это функция, которую вызывает аккордеон, чтобы визуализировать каждый заголовок отдельно. То есть, если компонент монтируется с 10 заголовками, эта функция вызывается 10 раз.

  _renderHeader = section => {

      let rotateAnimation = this.state.animValue.interpolate({
          inputRange: [250, 450],
          outputRange: ['0deg', '180deg']
      });
    const customStyle = {
      transform:[{rotate:rotateAnimation}]
    };

    return (
        <View style={styles.header}>
          <View style={styles.headerTextContainer}>
            <Text style={styles.headerText}>{section['title']}</Text>
              <Animated.View style={[{marginLeft: 10}, customStyle]}>
                <TouchableWithoutFeedback >
                  <Ionicons name="md-arrow-dropdown" size={20} color={EStyleSheet.value('$textColor')} />
                </TouchableWithoutFeedback>
              </Animated.View>
          </View>

        </View>
    );
  };

Ниже представлена ​​функция аккордеона, которая срабатывает при каждом щелчке по заголовку. Здесь я запускаю функцию анимации.

 _updateSections = activeSections => {
    console.log(activeSections)
    this.handleSelect()


   //unrelated code...


Дополнительная информация

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

    this.state={
      activeSections: [],
      animValue: [new Animated.Value(250),new Animated.Value(250),new Animated.Value(250),new Animated.Value(250),new Animated.Value(250),]
    }

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

Я столкнулся с этой ошибкой во время моей попытки:

TypeError: TypeError: undefined не является объектом (оценивается как _this.state.animValue [i] .interpolate ')

1 Ответ

0 голосов
/ 25 октября 2019

Решение!

Через пару долгих часов я смог найти решение! Публикация сообщений для тех, у кого могут быть похожие проблемы.

Сначала вам нужно отредактировать свое состояние. Это позволяет каждому значку иметь свое собственное значение Animated.Value. Я жестко запрограммировал много новых animated.values ​​для видимости, но для динамического выделения я буду выдвигать новое значение, а затем назначать его в следующих шагах ниже.

      animValue: [
        new Animated.Value(250),
        new Animated.Value(250),
        new Animated.Value(250),
        new Animated.Value(250),
        new Animated.Value(250),
        new Animated.Value(250),
        new Animated.Value(250),
      ],

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

<Animated.View key={1} style={[{marginLeft: 10}, {transform:[{rotate: this.state.animValue[i].interpolate({
        inputRange: [250, 450],
        outputRange: ['0deg', '180deg']})}]}]}>

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

handleSelect = (i) => {
    this.state.animValue[i]._value > 250
      ? Animated.timing(this.state.animValue[i], {
          toValue: 250,
          duration: 500
        }).start()
      : Animated.timing(this.state.animValue[i], {
          toValue: 450,
          duration: 500
        }).start();
  };

Надеюсь, это поможет любой потерянной душе, которая может иметь ту же проблему, что и я!

...