React Native - Animations
React Native - Animations
Section titled “React Native - Animations”React Native provides powerful APIs for creating animations. This chapter focuses on the Animated API for fine-grained control over animated values, and briefly mentions LayoutAnimation for simpler transitions. We’ll use functional components and Hooks.
Using the Animated API
Section titled “Using the Animated API”The Animated API allows you to create time-based animations (like Animated.timing), spring-based animations (Animated.spring), or decay animations (Animated.decay). You typically animate specific style properties of special Animated components (e.g., Animated.View, Animated.Text, Animated.Image).
We’ll create an example where a box changes its width and height when pressed.
AnimatedBox.js
import React, { useRef, useState } from 'react';import { View, StyleSheet, Animated, TouchableOpacity, Text } from 'react-native';
const AnimatedBox = () => { // useRef to store Animated values, persisting them across re-renders const animatedWidth = useRef(new Animated.Value(100)).current; const animatedHeight = useRef(new Animated.Value(100)).current; const animatedOpacity = useRef(new Animated.Value(1)).current;
const [isExpanded, setIsExpanded] = useState(false);
const animateBox = () => { const newWidth = isExpanded ? 100 : 200; const newHeight = isExpanded ? 100 : 200; const newOpacity = isExpanded ? 1 : 0.5;
// Parallel animations Animated.parallel([ Animated.timing(animatedWidth, { toValue: newWidth, duration: 500, // milliseconds useNativeDriver: false, // 'true' for better performance on non-layout properties }), Animated.timing(animatedHeight, { toValue: newHeight, duration: 700, useNativeDriver: false, }), Animated.timing(animatedOpacity, { toValue: newOpacity, duration: 700, useNativeDriver: true, // Opacity can use native driver }) ]).start(() => { setIsExpanded(!isExpanded); // Toggle state after animation completes }); };
// Create an animated style object const animatedStyle = { width: animatedWidth, height: animatedHeight, opacity: animatedOpacity, };
return ( <View style={styles.container}> <TouchableOpacity onPress={animateBox}> <Animated.View style={[styles.box, animatedStyle]} /> </TouchableOpacity> <Text style={styles.instructionText}> Tap the box to {isExpanded ? 'collapse' : 'expand'} it. </Text> </View> );};
const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#f0f0f0', }, box: { backgroundColor: 'royalblue', // Initial dimensions are set by Animated.Value }, instructionText: { marginTop: 20, fontSize: 16, color: '#333', }});
export default AnimatedBox;Explanation
Section titled “Explanation”useRefandAnimated.Value: We initializeAnimated.Values insideuseRefto ensure they persist across renders without being recreated.animatedWidth.currentgives access to theAnimated.Valueinstance.Animated.timing: Creates an animation that transitions a value over a specified duration. Other types includeAnimated.spring(physics-based spring) andAnimated.decay(initial velocity gradually slows to a stop).Animated.parallel: Runs multiple animations simultaneously. Other combinators includeAnimated.sequence(animations one after another) andAnimated.stagger(staggered start times).start(): Begins the animation. It can take an optional callback that fires upon completion.Animated.View: A special component that can have its style properties animated. You must useAnimated.View,Animated.Text,Animated.Image, etc., or create your own animatable components usingAnimated.createAnimatedComponent().useNativeDriver: true: For performance, offloads animations to the native thread. This only works for non-layout properties (liketransform,opacity). Layout properties (width,height,margin,padding,top,left, etc.) must useuseNativeDriver: false(default) and run on the JS thread.
When you tap the blue box, it will smoothly animate its width, height, and opacity. Tapping again will reverse the animation.
LayoutAnimation (Simpler Transitions)
Section titled “LayoutAnimation (Simpler Transitions)”LayoutAnimation provides a simpler way to animate transitions when layout properties change (e.g., due to state updates). It animates views to their new positions when the next layout calculation happens.
LayoutAnimationExample.js
import React, { useState } from 'react';import { View, StyleSheet, TouchableOpacity, Text, LayoutAnimation, UIManager, Platform} from 'react-native';
// Enable LayoutAnimation for Android (iOS is enabled by default)if (Platform.OS === 'android') { if (UIManager.setLayoutAnimationEnabledExperimental) { UIManager.setLayoutAnimationEnabledExperimental(true); }}
const LayoutAnimationExample = () => { const [boxSize, setBoxSize] = useState(100); const [isToggled, setIsToggled] = useState(false);
const toggleBox = () => { // Configure the animation type. // Options: LayoutAnimation.Presets.easeInEaseOut, .linear, .spring // Or define custom animation: LayoutAnimation.configureNext(config); LayoutAnimation.configureNext(LayoutAnimation.Presets.spring); setBoxSize(isToggled ? 100 : 200); setIsToggled(!isToggled); };
return ( <View style={styles.container}> <TouchableOpacity onPress={toggleBox}> <View style={[styles.box, { width: boxSize, height: boxSize }]} > <Text style={styles.boxText}>Tap Me</Text> </View> </TouchableOpacity> </View> );};
const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#f5fcff', }, box: { backgroundColor: 'mediumseagreen', justifyContent: 'center', alignItems: 'center', }, boxText: { color: 'white', fontWeight: 'bold' }});
export default LayoutAnimationExample;LayoutAnimation is simpler for global layout changes but less flexible than Animated. You call LayoutAnimation.configureNext() before the state change that causes the re-layout.
Choosing an Animation API
Section titled “Choosing an Animation API”- Use
Animatedfor complex, interactive animations, or when you need fine-grained control over animation values and sequences. - Use
LayoutAnimationfor simple, fire-and-forget animations of layout properties triggered by state changes. - For more advanced and performant animations, especially gesture-based ones, consider libraries like React Native Reanimated and React Native Gesture Handler.
Explore the official animation guides: https://reactnative.dev/docs/animations and https://reactnative.dev/docs/layoutanimation.