🎮 Animation Control in React Native
The Remote Control for Your Animations
Imagine you have a toy car. You can make it go forward, stop it, make it go faster, or even make it do tricks. Animation Control is like having a remote control for your app’s animations!
In React Native, animations are like little robots that move things around on screen. But robots need instructions! That’s where Animation Control comes in—it lets you tell your animations exactly what to do and when.
🎯 What You’ll Learn
graph TD A["Animation Control"] --> B["Animated Event"] A --> C["Native Driver"] A --> D["Animation Callbacks"] A --> E["Stopping Animations"] A --> F["LayoutAnimation API"] B --> B1["Connect gestures to animations"] C --> C1["Super fast animations"] D --> D1["Know when animations finish"] E --> E1["Stop animations anytime"] F --> F1["Easy layout changes"]
1️⃣ Animated Event
What is it?
Think of Animated.event as a magical bridge. When you scroll, swipe, or touch the screen, it connects those finger movements directly to your animations!
Like a Puppet Show: Your finger is the puppeteer, and Animated.event is the strings connecting to the puppet (animation).
Why Use It?
Without Animated.event, you’d need to write lots of code to track every tiny finger movement. With it, scrolling can automatically fade things, resize them, or move them around—all connected like magic!
Simple Example
// Create an animated value
const scrollY = useRef(
new Animated.Value(0)
).current;
// Connect scroll position to animation
<Animated.ScrollView
onScroll={Animated.event(
[{ nativeEvent: {
contentOffset: { y: scrollY }
}}],
{ useNativeDriver: true }
)}
>
{/* Your content */}
</Animated.ScrollView>
What happens:
- User scrolls up →
scrollYgoes up - User scrolls down →
scrollYgoes down - No extra code needed!
Real-Life Example
When you scroll Instagram:
- Header shrinks as you scroll down
- Profile picture fades slightly
- All connected through
Animated.event!
2️⃣ Native Driver
What is it?
The Native Driver is like having a super-fast delivery truck for your animations!
Without Native Driver: Your animations go through JavaScript (slow path, like walking).
With Native Driver: Animations go directly to the phone’s brain (fast path, like flying!).
Why It Matters
graph LR A["Animation"] --> B{Native Driver?} B -->|No| C["JavaScript Thread"] C --> D["Bridge"] D --> E["Native Thread"] E --> F["Screen"] B -->|Yes| G["Native Thread"] G --> F
With Native Driver = 60 FPS smooth animations!
How to Use It
Just add one line:
Animated.timing(fadeAnim, {
toValue: 1,
duration: 500,
useNativeDriver: true // Magic line!
}).start();
What Works with Native Driver?
| ✅ Works | ❌ Doesn’t Work |
|---|---|
| opacity | width |
| transform | height |
| translateX | margin |
| translateY | padding |
| scale | borderRadius |
| rotate | color |
Remember: If you’re changing SIZE or POSITION (not transform), use useNativeDriver: false.
3️⃣ Animation Callbacks
What is it?
Callbacks are like getting a text message when something finishes. Your animation can tell you: “Hey, I’m done now!”
Why Use Them?
- Start a new animation after one finishes
- Show a message when animation completes
- Clean up resources
- Chain multiple animations
The Start Callback
Animated.timing(fadeAnim, {
toValue: 1,
duration: 500,
useNativeDriver: true
}).start(({ finished }) => {
// This runs when animation ends!
if (finished) {
console.log('Animation completed!');
// Start next animation
// Show success message
// Navigate to new screen
} else {
console.log('Animation was stopped');
}
});
The finished Property
graph TD A["Animation Starts"] --> B{Did it complete?} B -->|Yes| C["finished = true"] B -->|No - Stopped| D["finished = false"] C --> E["Run success code"] D --> F["Run stopped code"]
Chaining Animations Example
// Fade in, then scale up!
Animated.timing(fadeAnim, {
toValue: 1,
duration: 300,
useNativeDriver: true
}).start(() => {
// After fade, start scale
Animated.spring(scaleAnim, {
toValue: 1.2,
useNativeDriver: true
}).start();
});
4️⃣ Stopping Animations
What is it?
Sometimes you need to tell an animation “STOP!” Maybe the user navigated away, or they pressed a cancel button.
Why Stop Animations?
- User leaves the screen
- User cancels an action
- Need to start a different animation
- Prevent memory leaks
Two Ways to Stop
Method 1: Stop All on a Value
// Stop ALL animations on this value
fadeAnim.stopAnimation(value => {
console.log('Stopped at:', value);
});
Method 2: Keep Reference and Stop
// Store the animation
const animation = Animated.timing(
fadeAnim,
{ toValue: 1, duration: 1000 }
);
// Start it
animation.start();
// Stop it anytime
animation.stop();
Stop vs Reset
graph TD A["Animation Running"] --> B{What to do?} B -->|Stop| C["stopAnimation"] B -->|Reset| D["setValue"] C --> E["Stays where it is"] D --> F["Goes back to start"]
Stop: Freezes at current position Reset: Goes back to starting value
// Stop where it is
fadeAnim.stopAnimation();
// OR reset to beginning
fadeAnim.setValue(0);
Cleanup Example
useEffect(() => {
const animation = Animated.timing(
fadeAnim,
{ toValue: 1, duration: 2000 }
);
animation.start();
// Stop when component unmounts
return () => animation.stop();
}, []);
5️⃣ LayoutAnimation API
What is it?
LayoutAnimation is like magic for your app’s layout! Instead of writing complex animation code, you just say “Hey, animate whatever changes next!”
The Magic of LayoutAnimation
graph TD A["Tell LayoutAnimation<br>to watch"] --> B["Change your state"] B --> C["React re-renders"] C --> D["LayoutAnimation<br>animates the change!"]
It’s like having an autopilot for animations!
Basic Usage
import { LayoutAnimation } from 'react-native';
function toggleBox() {
// Tell it to animate next change
LayoutAnimation.configureNext(
LayoutAnimation.Presets.easeInEaseOut
);
// Now change state
setIsExpanded(!isExpanded);
}
Built-in Presets
| Preset | What it does |
|---|---|
linear |
Steady speed |
spring |
Bouncy effect |
easeInEaseOut |
Smooth start & end |
Example: Expanding Box
const [big, setBig] = useState(false);
const toggle = () => {
LayoutAnimation.configureNext(
LayoutAnimation.Presets.spring
);
setBig(!big);
};
return (
<View
style={{
width: big ? 200 : 100,
height: big ? 200 : 100,
backgroundColor: 'blue'
}}
/>
);
No Animated.Value needed! No interpolation! Just works!
Android Setup
For Android, you need to enable it once:
import { UIManager, Platform } from 'react-native';
if (Platform.OS === 'android') {
UIManager.setLayoutAnimationEnabledExperimental
&& UIManager.setLayoutAnimationEnabledExperimental(true);
}
When to Use LayoutAnimation vs Animated
| Use LayoutAnimation | Use Animated |
|---|---|
| Layout changes | Continuous animations |
| Adding/removing items | Scroll-based effects |
| Size changes | Gesture responses |
| Simple transitions | Complex sequences |
🧠 Quick Summary
graph TD A["Animation Control"] --> B["Animated.event"] A --> C["Native Driver"] A --> D["Callbacks"] A --> E["Stopping"] A --> F["LayoutAnimation"] B --> B1["Connect gestures"] C --> C1["60 FPS performance"] D --> D1["Know when done"] E --> E1["Cancel anytime"] F --> F1["Magic layout changes"]
🚀 You Did It!
You now understand the five superpowers of Animation Control:
- Animated.event - Connect touches to animations
- Native Driver - Super-fast animations
- Callbacks - Know when animations finish
- Stopping - Cancel animations safely
- LayoutAnimation - Easy layout transitions
Go build something amazing! Your animations will now be smooth, controlled, and professional! 🎉
