React-Native动画高度变化

时间:2018-04-03 18:30:31

标签: react-native

我有一个React-Native组件,其大小由其内容决定,必须从互联网上加载。随着加载的进行,它的大小会有一些变化,我希望看起来更平滑。

我现在所做的工作是在从onLayout获取新高度后为视图的scaleY属性设置动画。问题是我只能设置动画的初始比例从onLayout之后开始,所以暂时,视图是新​​的大小,然后开始从旧大小动画到新大小。

如果有一种方法可以获得新的布局大小,那么它会变得很棒但是我找不到办法来做到这一点。

另一种选择是将视图放在另一个视图中,将其剪切到旧的高度,直到可以调整其比例,但我不知道如何在不影响视图本身大小的情况下执行此操作。剪辑的时刻可能也会以自己的方式看起来很奇怪。

1 个答案:

答案 0 :(得分:0)

我最近回答了一个与此问题类似的问题:
How do you animate the height in react native when you don't know the size of the content?

但是我会在这里再次发布答案。
对于您的情况,请在加载内容后尝试运行动画功能。


大家好,希望还不晚...

适用于任何使用View高度处理React Native动画的人。
我知道这很烦人:

✖️React Native动画似乎不支持布局样式(例如,宽度和高度)
✖️LayoutAnimation看起来很难调查
W️希望使用一种官方方式制作动画,而不是安装第三方程序包
✖️有时内容可能很大,破坏了您的视图样式

这是我为您提供的解决方案(类组件方式):

首先,将动画值设置为状态:

state = { height: new Animated.Value(0) };

接下来,通过动画插值设置动画视图的max height

const maxHeight = this.state.height.interpolate({ 
  inputRange: [0, 1], 
  outputRange: [0, 2000]  // <-- any value larger than your content's height
};
return (<Animated.View style={[styles.box, { maxHeight: maxHeight }]} />); 
// any other fixed styles in styles.box

然后,将动画设置在您调用的function内,
componentDidMount(如果希望它在呈现后立即显示):

// or in any function that users interact
componentDidMount() {
  Animated.timing(this.state.formHeight, {
    toValue: 1,
    duration: 500,           // <-- animation duration
    easing: Easing.linear,   // <-- or any easing function
    useNativeDriver: false   // <-- need to set false to prevent yellow box warning
  }).start();
}

请注意,因为布局样式不支持将useNativeDriver设置为true


样本

因此,下面是供您与之交互的示例,
随时复制并粘贴到您的React Native项目以进行尝试:

import React, { PureComponent } from 'react';
import { Animated, Button, Easing, View, Text, StyleSheet } from 'react-native';

class AnimateBox extends PureComponent {
  state = { opacity: new Animated.Value(0), height: new Animated.Value(0) };

  showContent = () => {
    const { opacity, height } = this.state;

    Animated.timing(height, {
      toValue: 1,
      duration: 500,
      easing: Easing.linear,
      useNativeDriver: false  // <-- neccessary
    }).start(() => {
      Animated.timing(opacity, {
        toValue: 1,
        duration: 500,
        easing: Easing.linear,
        useNativeDriver: false  // <-- neccessary
      }).start();
    });
  };

  render() {
    const { opacity, height } = this.state;
    const maxHeight = height.interpolate({ 
      inputRange: [0, 1], 
      outputRange: [0, 1000]  // <-- value that larger than your content's height
    });

    return (
      <View style={styles.box}>
        <Animated.View style={{ opacity: opacity, maxHeight: maxHeight }}>
          <Text style={styles.content}>
            Lorem Ipsum is simply a dummy text of the printing and typesetting industry.
            Lorem Ipsum has been the industry's standard dummy text ever since the 1500s,
            when an unknown printer took a galley of type and scrambled it to make a type specimen book.
            It has survived not only five centuries, but also the leap into electronic typesetting,
            remaining essentially unchanged. It was popularised in the 1960s with the release of
            Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
          </Text>
        </Animated.View>
        <View style={styles.spacing}>
          <Button title="Show content" onPress={this.showContent} />
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  box: {
    backgroundColor: '#fff',
    marginHorizontal: 15,
    paddingHorizontal: 15
  },
  spacing: {
    paddingVertical: 10
  },
  content: {
    fontSize: 16,
    lineHeight: 30,
    color: '#555'
  }
});


export default AnimateBox;

快乐编码:)