大家好,希望还不算太晚...
适用于在视图高度上处理 React Native 动画的任何人。
我知道这很烦人:
✖️React Native动画似乎不支持布局样式(例如宽度和高度)
✖️ LayoutAnimation 看起来很难调查
✖️ 希望用官方的方式制作动画而不是安装第三方包
✖️ 有时内容可能会影响您的视图样式
所以这是我给你的解决方案(类组件方式):
首先,在状态中设置动画值:
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;
快乐编码:)
更多解释(2021 年 2 月 3 日编辑)
如 React Native 文档中所述:
https://reactnative.dev/docs/animations#caveats
原生驱动程序目前并不支持您可以使用 Animated 执行的所有操作。主要限制是您只能为非布局属性设置动画:像 transform 和 opacity 这样的东西会起作用,但 Flexbox 和 position 属性不会。
禁用useNativeDriver可以为opacity和transform以外的样式设置动画,但实际上增加了JS线程的工作量,因为JS线程需要计算每一帧的UI。 p>
在 React Native 0.62 的博客中:
https://reactnative.dev/blog/2020/03/26/version-0.62#deprecations
现在需要设置 useNativeDriver 以支持将来切换默认。
您必须在React native v0.62或以上的动画选项中设置useNativeDriver以防止出现任何警告。