Есть ли способ анимировать увеличенный размер представления при добавлении новых дочерних элементов?

В настоящее время я использую LayoutAnimation для анимации представления при добавлении дочерних элементов. Однако, поскольку LayoutAnimation заставляет анимировать все глобально, и я не могу легко использовать встроенную библиотеку Animated для моего варианта использования, мне интересно, может ли react-native-reanimated помочь.

Вот пример моего текущего решения: https://snack.expo.io/@insats/height-adapation

Вот как выглядит результат этого:

введите здесь описание изображения

Есть ли способ добиться того же без использования LayoutAnimation? Я просмотрел все примеры в react-native-reanimated и прочитал документы, но я все еще не уверен, возможно ли это сделать или как мне начать. Я думал об использовании Animated, чтобы переместить оболочку элемента из области просмотра и «прокрутить» ее вверх (используя transform translateY) при добавлении элементов, но для этого потребуется фиксированная высота, которой у меня нет.


person Adam Gerthel    schedule 09.12.2019    source источник


Ответы (1)


У меня есть 2 подхода, которые я могу предложить из головы:

  1. Вы можете настроить LayoutAnimation только тогда, когда желаемое состояние изменилось. Если вы используете хуки, это будет слишком просто:

    const [state,setState] = useState([]);
    useEffect(()=>{
       /*rest code*/
       LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
    },[state])
    

    Или, если вы используете компонент класса, вы можете поймать желаемое изменение состояния в componentDidUpdate:

    componentDidUpdate(prevProps,prevState){
       if(prevState.items!==state.items){
           LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
       }
    }
    
  2. Вы можете использовать onLayout функцию просмотра:

    addItem = () => {
       this.setState({
          items: [...this.state.items, {title:'An item',isNew:true}]
       })
    }; 
    renderItems = () => {
       return this.state.items.map((item, index) => {
          let opacity = new Animated.Value(0);
          return (
            <Animated.View onLayout={({nativeEvent})=>{
               if(this.state.item.isNew){
                  // here you got the height from nativeEvent.layout.height
                  // Then you have to store the height animate height and opacity to its precise value 
                  // PS I used opacity:0 to calculate the height
                 }
               }} key={index} style={[styles.item,{opacity}>
              <Text>{item.title}</Text>
            </View>
           )
       });
    };
    

Когда дело доходит до react-native-reanimated, я считаю его более быстрой версией библиотеки Animated react-native. Так что в любом случае вам придется рассчитать высоту!

person OriHero    schedule 09.12.2019
comment
Спасибо за советы! Первое предложение с LayoutAnimation — это в основном то, что я уже делаю, но оно создает странное поведение макета во всем приложении. Я смотрю на ваш второй подход, потому что мне вполне удобно работать с Animated, но я понятия не имел о onLayout. В вашем примере вы анимируете вход одного нового элемента, верно? Но в моем случае я бы хотел анимировать высоту самого списка, не так ли? - person Adam Gerthel; 09.12.2019
comment
Я знал, что ты собираешься оживить высоту. Прежде чем анимировать высоту, вы должны сначала вычислить высоту. По этой причине сначала визуализируйте элемент с непрозрачностью 0, а когда вы получите высоту, вы установите непрозрачность на 1 и анимируете высоту, как указано в комментариях! - person OriHero; 09.12.2019
comment
Вы имели в виду что-то вроде этого? snack.expo.io/@insats/calm-tortillas - person Adam Gerthel; 09.12.2019
comment
Да, именно, но вместо того, чтобы анимировать непрозрачность после оценки высоты, вы можете интерполировать высоту! Так будет смотреться намного ровнее! Я впервые встречаю человека, который думает точно так же, как я! - person OriHero; 09.12.2019
comment
Ха-ха, рад это слышать :D Я внес небольшое изменение в закуску, на которую ссылался в своем последнем комментарии, чтобы сделать ее более плавной, запустив их параллельно. Недостатком этого подхода является то, что useNativeDriver не поддерживает анимацию высоты:/ - person Adam Gerthel; 10.12.2019
comment
Ага. Кроме того, onLayout не рекомендуется при рендеринге нескольких элементов! Кстати классно смотрится! - person OriHero; 10.12.2019
comment
Я нашел хороший способ справиться с этим, используя onLayout для оболочки и используя высоту для анимации, эквивалентную высоте оболочки. Работает супер и с хорошей производительностью тоже. Спасибо за помощь! - person Adam Gerthel; 10.12.2019