How to animate view and text in React Native using Animated API
With the advancement in UI/UX, the importance of animations in web/mobile applications has increased since they contribute to a great user experience. Animations enhance the user experience with the help of visual communication, simplify complex information, guide user attention, add emotional appeal, aid in storytelling, and promote interactivity. Several third-party libraries allow us to add animations in React Native applications. For example, react-native-animatable, react-native-motion, Lottie and react-native-reanimated. However, React Native provides us with the Animated API that makes our life easier regarding animations.
Animated API
The Animated API in React Native allows developers to create and manage animated components and animations. To summarize its functionality and key features:
-
Animated values: Developers can create animated values like numbers or colors and link them to UI component properties. These values can be updated over time to drive animations.
-
Interpolation: Animated values can be interpolated to map input ranges to output ranges. This allows developers to create animations that smoothly change properties based on the progress of the animation.
-
Animated components: React Native provides animated versions of common components, such as
Animated.View,Animated.Text, andAnimated.Image. These components can be animated by linking their properties to animated values. -
Animation functions: The Animated API offers functions like
Animated.timingfor timing-based animations,Animated.springfor spring-based animations, andAnimated.sequenceandAnimated.parallelfor combining multiple animations. -
Animation methods: The
Animatedlibrary provides methods to control and manage animations, such asstart(),stop(), andaddListener(). These methods allow developers to control the lifecycle and behavior of animations.
Animate View and Text
We can use any of the above-mentioned features of Animated API along with its components, Animated.View and Animated.Text, to animate any view of the application. The two most common animation functions are Animated.timing and Animated.spring, so we will use one of these for our examples.
Spring the ball
Let’s see an example where we have slightly bounced a ball outward using the spring animation, along with the animated view.
import {StyleSheet, Animated, Button, View } from 'react-native';
import {useRef} from "react";
function App() {
const move = useRef(new Animated.Value(0)).current;
const animation = () => {
Animated.spring(move, {
toValue: 2,
friction: 3,
useNativeDriver: true,
}).start();
};
return (
<View>
<Animated.View style={[styles.ball, { transform: [{scale: move}]}]} />
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center', marginTop: 150}}>
<Button title="Spring the ball" onPress={animation} />
</View>
</View>
);}
export default App;
const styles = StyleSheet.create({
ball: {
height: 100,
width: 100,
borderRadius: 150/2,
backgroundColor: 'red',
marginTop: 150,
marginRight: 'auto',
marginBottom: 'auto',
marginLeft: 'auto'
}
});Explanation
-
Line 1: We import
Animatedfromreact-native. -
Line 5: We initialize the animation value,
move, usingAnimated.Valueto . The ball animates as per this value. -
Lines 7—13: We create a function,
animation, which will cause the spring animation, that is, make the ball bounce outward.-
Line 8: We initialize the spring animation function,
Animated.spring(move, configurations), which takes the animated value to be changed as the first argument and certain configurations as the second argument. -
Line 9: This is the value we want our animation value,
move, to change to. It changes the value ofmovefrom to .
-
-
Line 17: We pass the animation value to the
Animated.Viewcomponent. This renders the animation. -
Line 19: We create a button to make the call to the animation function once clicked.
Fade-in the text
Let’s see an example where we’ve animated the text using the timing animation. The text will fade in.
import {StyleSheet, Animated, Button, View } from 'react-native';
import {useRef} from "react";
function App() {
const fade = useRef(new Animated.Value(0)).current;
const animation = () => {
Animated.timing(fade, {
toValue: 1,
duration: 2000,
useNativeDriver: true,
}).start();
};
return (
<View>
<Animated.Text style={[styles.text, {opacity:fade}]}>Hello World</Animated.Text>
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center', marginTop: 100}}>
<Button title="Fade In Text" onPress={animation} />
</View>
</View>
);}
export default App;
const styles = StyleSheet.create({
text:{
marginTop:50,
marginLeft:150,
color: '#000080',
fontSize: 80
}
});Explanation
-
Line 1: We import
Animatedfromreact-native. -
Line 5: We initialize the animation value,
fade, to usingAnimated.Value. The text fades in as per this value. -
Lines 7—13: We create a function,
animation, that will cause the text to fade in because of the timing animation.-
Line 8: We initialize the spring animation function,
Animated.timing(fade, configurations), which takes the animated value to be changed as the first argument and certain configurations as the second argument. -
Line 9: This is the value we want our animation value,
fade, to change to. It changes the value offadefrom to . -
Line 10: This is the duration of the animation. We have set it to milliseconds.
-
-
Line 17: We pass the animation value to the
Animated.Textcomponent. This renders the animation. -
Line 19: We create a button to make the call to the animation function once clicked.
Example
As our final example, we’ve created a demo application that will demonstrate the use of multiple animated methods, along with its components Animated.View and Animated.Text.
Click “Run” to execute the code. Once the server starts, you can click the URL next to “Your app can be found at:” to view the application in the new browser tab.
import Night from "./components/Night"
import Shooting from "./components/Shootingstar"
import {StyleSheet, Animated, TouchableOpacity, Text, View } from 'react-native';
import { useEffect, useRef, useState } from "react";
function App() {
const [clicked, setClick] = useState(false);
const [mode, setMode] = useState('');
const [bg, setBG] = useState('white');
const fade = useRef(new Animated.Value(0)).current;
const move = useRef(new Animated.Value(-1)).current;
const dec = useRef(new Animated.Value(-200)).current;
const textmove = useRef(new Animated.Value(0)).current;
const animation1 = () => {
setClick(!clicked)
setBG('#151931')
setMode('first')
Animated.sequence([
Animated.timing(fade, {
toValue: 1,
duration: 2000,
useNativeDriver: true,
}),
Animated.spring(move, {
toValue: 0.75,
friction: 3,
useNativeDriver: true,
})
]).start();
};
const animation2 = () => {
setClick(!clicked)
setBG('#151931')
setMode('second')
Animated.decay(dec, {
toValue: 300,
duration: 5000,
velocity: 1.5,
deceleration: 0.998,
useNativeDriver: true
}).start();
};
const removeAnimation1 = () => {
setBG('white')
setClick(!clicked)
setMode('')
Animated.sequence([
Animated.spring(move, {
toValue: -1,
useNativeDriver: true,
}),
Animated.timing(fade, {
toValue: 0,
useNativeDriver: true,
})
]).start();
};
const removeAnimation2 = () => {
setClick(!clicked)
setBG('white')
setMode('')
Animated.timing(dec, {
toValue: -200,
useNativeDriver: true
}).start();
};
useEffect(() => {
Animated.spring(textmove, {
toValue: 1,
duration: 1000,
useNativeDriver: true,
}).start();
}, [textmove]);
return (
<View style={{backgroundColor: bg, height: '100vh', paddingTop:'80px'}}>
{mode === 'first' && <Night fade={fade} move={move} />}
{mode === 'second' && <Shooting dec={dec} />}
{mode === '' && <>
<View>
<Animated.Text style={[styles.text1,{ transform: [{scale: textmove}]}]}>Hello! 👋</Animated.Text>
</View>
</>}
{clicked && <>
<View style={styles.container3}>
{mode === 'first' && <TouchableOpacity style={[styles.button, {backgroundColor: 'grey'}]} onPress={removeAnimation1}>
<Text style={{ color:'white'}}>Back</Text>
</TouchableOpacity>}
{mode === 'second' && <TouchableOpacity style={[styles.button, {backgroundColor: 'grey'}]} onPress={removeAnimation2}>
<Text style={{ color:'white'}}>Back</Text>
</TouchableOpacity>}
</View>
</>}
{!clicked && <>
<View style={styles.container3}>
<TouchableOpacity style={[styles.button, {backgroundColor:'#000080'}]} onPress={animation1}>
<Text style={{ color:'white'}}>Show me the starry night</Text>
</TouchableOpacity>
<TouchableOpacity style={[styles.button, {backgroundColor:'#000080'}]} onPress={animation2}>
<Text style={{ color:'white'}}>Show me the shooting star</Text>
</TouchableOpacity>
</View>
</>}
</View>
);}
export default App;
const styles = StyleSheet.create({
container1:{
flexDirection: 'row',
flexWrap: 'wrap',
flex: 1,
justifyContent: 'space-around'
},
container2:{
flexDirection: 'row',
flexWrap: 'wrap',
flex: 1,
justifyContent: 'space-between',
marginTop: 200,
},
container3:{
flexDirection: 'row',
flexWrap: 'wrap',
flex: 1,
justifyContent: 'space-around',
marginRight:'400px',
marginLeft:'400px'
},
text1:{
marginLeft:'600px',
color: '#000080',
fontSize: 80
},
button: {
alignItems: 'center',
height: 40,
width: 200,
marginTop: 120,
justifyContent: 'center',
borderRadius:'10px'
},
});The execution of the code above displays the main application page that demonstrates the use of Animated.Text and Animated.spring. The main page has two buttons: one to show the starry night and the other to show the shooting star. The starry night shows the use of Animated.View , Animated.timing, Animated.spring and Animated.sequence. On the other hand, the shooting star demonstrates the uses of Animated.View, and Animated.decay.
Free Resources