Как вы можете оживить высоту, реагируя на родной, когда вы не знаете размер содержимого?

В реакции-native, как вы анимируете размер представления, когда вы не знаете размер его содержимого?

Скажем, высота представления может быть от 0 до 400 пикселей, а контент может расти и динамически уменьшаться, и вы хотите оживить любые изменения высоты.

В принципе, я ищу, чтобы воспроизвести поведение LayoutAnimation без использования LayoutAnimation, но используя Animated.

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

Ответ 1

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

LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);

Вы можете использовать разные пресеты:

Ответ 2

Вам нужно будет добавить какое-то масштабирование по размеру, возможно, с процентами для лучшего эффекта.

Прежде всего вам нужно будет использовать Animated.View вместо View.

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

        <Animated.View style={[ styles.someStyleYouMade,
          {
            transform: [
              // scaleX, scaleY, scale, theres plenty more options you can find online for this.
              {  scaleX: ViewScaleValue } // this would be the result of the animation code below and is just a number.
            ]
          } 
        ]}
        >

Эта следующая часть в основном представляет собой пример анимированного API, вы должны написать что-то вроде этого (обычай так, как вы хотите), и когда этот скрипт будет вызван, он будет анимироваться любым способом, который вы укажете.

  Animated.timing(                    // Animate over time
    this.state.ViewScale,             // The animated value to drive, this would be a new Animated.Value(0) object.
    {
      toValue: 100,                   // Animate the value
      duration: 5000,                 // Make it take a while
    }
  ).start();

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

(это войдет в вашу функцию render() но до return(). ViewScaleValue войдет в преобразование Animated.View)

const ViewScaleValue = this.state.ViewScale.interpolate({
  inputRange: [0, 25, 50, 75, 100],
  outputRange: [0, .5, 0.75, 0.9, 1]
});

весь этот код заставит ViewScaleValue, простое число, оживить от 0 до 100, быстро, а затем медленно (из-за интерполяции) и применить каждую итерацию анимации к преобразованию Animated.View.

Прочитайте Animated API рядом с этим, чтобы получить хорошее представление об этом.

Ответ 3

Метод, который я выбрал, состоит в том, чтобы провести проходы макета, получая высоту "усеченного" компонента и высоту "полноразмерного" компонента (вам нужен способ, чтобы усеченная высота была детерминированной, обычно, зная, как визуализировать "ряд" контента). По сути, перед тем, как получить эти значения, вы представляете их как два отдельных представления, которые скрыты:

hidden: {
  position: 'absolute',
  left: 0,
  top: 0,
  opacity: 0,
},

Используйте onLayout, чтобы захватить их высоту:

const onLayoutTruncated = ({nativeEvent}: LayoutChangeEvent) => {
  if (!doneProcessing) {
    truncatedHeight = nativeEvent.layout.height;
    checkIfDoneProcessingLayout();
  }
};

const onLayoutFull = ({nativeEvent}: LayoutChangeEvent) => {
  if (!doneProcessing) {
    fullHeight = nativeEvent.layout.height;
    checkIfDoneProcessingLayout();
  }
};

checkIfDoneProcessingLayout() проверит, установлены ли оба truncatedHeight и fullHeight, и изменит состояние, если они оба (doneProcessing = true).

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

const expandingHeight = animatedValue.interpolate({
  inputRange: [0, 1],
  outputRange: [truncatedHeight, fullHeight],
});

Запустите растягивающую/сворачивающуюся анимацию при нажатии, используя Animated.timing

Animated.timing(animatedValue, {toValue: isExpanded ? 0 : 1, easing: SOME_EASING_FUNCTION, duration: SOME_DURATION}).start();