Vega supports three main approaches for creating animations in your Fire TV apps:
-
Animated API (built into React Native) - No additional dependencies required. Best for simple programmatic animations like fades, slides, and basic transitions. Great for learning animation fundamentals and interactive UI responses.
-
React Native Reanimated (
@amazon-devices/react-native-reanimated) - Runs animations on the UI thread for better performance. Best for complex animations, gesture-based interactions, and smooth 60fps experiences. Recommended for production apps. -
Lottie (
@amazon-devices/lottie-react-native) - Renders designer-created animations exported from After Effects. Best for complex vector animations, brand animations, and illustrations.
In this tutorial, we’ll build an interactive button with the Animated API that moves to a random position when clicked. We’ll start with the hello-world template and add animation functionality to it.
Step 1: Import Animated API and useRef
Open your App.tsx file and update the imports at the top. Add useRef to the React import and add Animated to the react-native imports:
import React, {useState, useRef} from 'react'; // Add useRef here
import {
StyleSheet,
Text,
ImageBackground,
View,
Image,
Animated // Add Animated here
} from 'react-native';
import {Link} from './components/Link';
What we’re adding:
useRef- React hook to create a persistent reference for our animation valueAnimated- React Native’s animation library for creating smooth animations
Step 2: Define the position reference
Inside the App component, add a position reference after the useState line:
export const App = () => {
const [image, setImage] = useState(images.vega);
// Add this line:
const position = useRef(new Animated.ValueXY({x: 0, y: 0})).current;
const styles = getStyles();
// ... rest of component
This creates a position reference using useRef to store the x and y coordinates. This value persists across component re-renders.
Step 3: Create the animation function
Add this function inside the App component, before the return statement:
export const App = () => {
const [image, setImage] = useState(images.vega);
const position = useRef(new Animated.ValueXY({x: 0, y: 0})).current;
const styles = getStyles();
// Add these functions:
const getRandomNumber = (min: number, max: number) => {
return Math.random() * (max - min) + min;
};
const handleImagePress = () => {
const randomX = getRandomNumber(-100, 100);
const randomY = getRandomNumber(-100, 100);
Animated.timing(position, {
toValue: {x: randomX, y: randomY},
duration: 1000,
useNativeDriver: false,
}).start();
};
return (
// ... rest of component
This creates an animation that moves the image to a random position over 1 second (1000 milliseconds).
Step 4: Wrap the image with Animated.View
Find the image View in your return statement and wrap it with Animated.View:
Before:
<View style={styles.image}>
<Image source={image} />
</View>
After:
<Animated.View style={[styles.image, position.getLayout()]}>
<Image source={image} />
</Animated.View>
The position.getLayout() applies the animated x and y values to the View’s style.
Step 5: Make the image clickable
Wrap the Image with a TouchableOpacity to make it clickable. You’ll need to import TouchableOpacity first:
Update imports:
import {
StyleSheet,
Text,
ImageBackground,
View,
Image,
Animated,
TouchableOpacity // Add this
} from 'react-native';
Update the image section:
<Animated.View style={[styles.image, position.getLayout()]}>
<TouchableOpacity onPress={handleImagePress}>
<Image source={image} />
</TouchableOpacity>
</Animated.View>
Complete Updated App.tsx
Here’s what your complete App.tsx should look like:
import React, {useState, useRef} from 'react';
import {
StyleSheet,
Text,
ImageBackground,
View,
Image,
Animated,
TouchableOpacity,
} from 'react-native';
import {Link} from './components/Link';
const images = {
vega: require('./assets/vega.png'),
learn: require('./assets/learn.png'),
support: require('./assets/support.png'),
build: require('./assets/build.png'),
};
export const App = () => {
const [image, setImage] = useState(images.vega);
const position = useRef(new Animated.ValueXY({x: 0, y: 0})).current;
const styles = getStyles();
const getRandomNumber = (min: number, max: number) => {
return Math.random() * (max - min) + min;
};
const handleImagePress = () => {
const randomX = getRandomNumber(-100, 100);
const randomY = getRandomNumber(-100, 100);
Animated.timing(position, {
toValue: {x: randomX, y: randomY},
duration: 1000,
useNativeDriver: false,
}).start();
};
return (
<ImageBackground
source={require('./assets/background.png')}
style={styles.background}>
<View style={styles.container}>
<View style={styles.links}>
<View style={styles.headerContainer}>
<Text style={styles.headerText}>Hello World!</Text>
<Text style={styles.subHeaderText}>
Select one of the options below to start your Vega journey 🚀
</Text>
</View>
<Link
linkText={'Learn'}
onPress={() => {
setImage(images.learn);
}}
testID="sampleLink"
/>
<Link
linkText={'Build'}
onPress={() => {
setImage(images.build);
}}
/>
<Link
linkText={'Support'}
onPress={() => {
setImage(images.support);
}}
/>
</View>
<Animated.View style={[styles.image, position.getLayout()]}>
<TouchableOpacity onPress={handleImagePress}>
<Image source={image} />
</TouchableOpacity>
</Animated.View>
</View>
<View style={styles.textContainer}>
<Text style={styles.text}>
💡 Edit App.tsx to change this screen and then come back to see your
edits. Click the image to see it move!
</Text>
</View>
</ImageBackground>
);
};
const getStyles = () =>
StyleSheet.create({
background: {
color: 'white',
flex: 1,
flexDirection: 'column',
},
container: {
flex: 6,
flexDirection: 'row',
alignItems: 'center',
},
headerContainer: {
marginLeft: 200,
},
headerText: {
color: 'white',
fontSize: 80,
marginBottom: 10,
},
subHeaderText: {
color: 'white',
fontSize: 40,
},
links: {
flex: 1,
flexDirection: 'column',
justifyContent: 'space-around',
height: 600,
},
image: {
flex: 1,
paddingLeft: 150,
},
textContainer: {
justifyContent: 'center',
flex: 1,
marginLeft: 190,
},
text: {
color: 'white',
fontSize: 40,
},
});
Try It Out!
Build and run the project on the Vega Virtual Device:
- Build:
npm install && npx react-native build-vega - Run:
vega run-app <your-package-file.vpkg>
Now when you click on the image on the right side of the screen, it will animate to a random position!
Last updated: Mar 3, 2026