Hi everyone, hope it's not too late...
for anyone who is dealing with React Native animation on view's height.
I know it is very annoying as:
✖️ React Native
animation seems not supporting layout styles (e.g. width and height)
✖️ LayoutAnimation
looks complicated to investigate
✖️ Wish to use an official way to animate instead of installing a third-party package
✖️ Sometimes content could be large to break your view styles
so here is my solution for you (class component way):
First, set the animated value in state:
state = { height: new Animated.Value(0) };
Next, set your animated view's max height
with animation interpolation:
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
After that, set the animation inside the function
you called,
or componentDidMount
if you want it to show as soon as it rendered:
// 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();
}
Be aware that don't set useNativeDriver
to true
as it is not supported on layout styles.
Sample
So below is a sample for you to interact with,
feel free to copy and paste to your React Native
project to have a try:
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;
Happy Coding :)
More Explanation (Edit in 03 Feb 2021)
As mentioned in React Native documentation:
https://reactnative.dev/docs/animations#caveats
Not everything you can do with Animated is currently supported by the native driver. The main limitation is that you can only animate non-layout properties: things like transform and opacity will work, but Flexbox and position properties will not.
Disabling useNativeDriver
can animate styles other than opacity
and transform
, but in fact increase the workload on JS thread as JS thread needs to calculate the UI on every frame.
And here in React Native 0.62's blog:
https://reactnative.dev/blog/2020/03/26/version-0.62#deprecations
Setting useNativeDriver is now required to support switching the default in the future.
You must need to set the useNativeDriver
in animation options on React native v0.62
or above to prevent any warnings.