How to animate a FlatList in React Native

The FlatList is a React Native framework component used to efficiently display data lists. Its purpose is to handle large lists by rendering only the items currently visible on the screen. As users scroll through the list, the FlatList dynamically renders and reuses components to display the new set of items in view. This approach provides better performance compared to rendering the entire list all at once.

In this Answer, we will be animating a FlatList using React Native’s Animated API.

The item

Let’s start by building the item that we will be using in the FlatList. We want to render each item as a bubble. We would also like the size of this item to be scalable to different screen sizes. Let’s see how we can achieve this using some basic components provided by the react-native library.

import React from "react";
import { Dimensions, View, StyleSheet } from "react-native";
const { width } = Dimensions.get("window");
export const ITEM_WIDTH = width * 0.8;
export const ITEM_HEIGHT = ITEM_WIDTH * 0.6;
const styles = StyleSheet.create({
item: {
width: ITEM_WIDTH,
height: ITEM_HEIGHT,
backgroundColor: "cornflowerblue",
borderRadius: 20,
},
});
const Item = () => {
return <View style={styles.item} />;
};
export default Item;
  • Lines 1–2: We import all the necessary components from React and React Native.

  • Line 4: Dimensions is used to get the dimensions of the device screen. We destructure the width property from the dimensions of the device’s window.

  • Lines 5–6: We calculate and export the ITEM_WIDTH and ITEM_HEIGHT . The width and height of the item are calculated based on the width of the output window.

  • Lines 8–15: We use StyleSheet.create to define styles for the item container. The container has a fixed width and height, background color of "cornflowerblue," and a border radius of 20, giving it rounded corners.

  • Lines 17–18: A functional component Item is created.

  • Line 21: We export functional component Item.

Animating the item

We want to animate our list to bubble up each item as it scrolls into view. The item will then render completely once it is completely in view. When the item scrolls out of view, we want it to bubble down and move back into the screen. While this may sound tricky, it can be implemented easily by modifying the opacity and scale of the list items. In order to trigger these animations, we would need to know the position of each item on the screen. This will let react-native know when to trigger which animation. The vertical position is commonly referred to as the y value of a component. We will be following the same convention in this Answer.

Basic setup

Before implementing any animations, we need to set up some basic values. We will also use the Item that we created earlier.

import React from "react";
import { Animated, Dimensions, StyleSheet } from "react-native";
import Item, { ITEM_HEIGHT as DEFAULT_ITEM_HEIGHT } from "./Item";
export const BUFFER = 10;
export const ITEM_HEIGHT = DEFAULT_ITEM_HEIGHT + BUFFER * 2;
const styles = StyleSheet.create({
item: {
marginVertical: BUFFER,
alignSelf: "center",
},
});

Let’s see what’s happening in the code:

  • Lines 1–2: We import Animated, Dimensions, and StyleSheet from the react-native library.

  • Line 3: We import the Item component and the ITEM_HEIGHT constant from the Item file. We alias ITEM_HEIGHT as DEFAULT_ITEM_HEIGHT for clarity in our calculations.

  • Line 5: We define a constant BUFFER with a value of 10. This buffer will be used to add padding around the item.

  • Line 6: We calculate a new ITEM_HEIGHT which includes the BUFFER on both the top and bottom, making it DEFAULT_ITEM_HEIGHT + BUFFER * 2.

  • Lines 8–11: We use StyleSheet.create to define styles for the component. We define an item style with the following properties:

    • marginVertical: BUFFER adds vertical margins of 10 units (top and bottom).

    • alignSelf: "center" centers the item horizontally within its parent container.

Setting up the scroll

Let’s define our animated item that responds to the scroll position. This will allow us to create the basic scrolling animation for the list by simply manipulating the y value. The first thing we need to do is to create a functional component, AnimatedItem , that takes three parameters: propitems, y, and index.

  • propitems is the object containing properties for color and text.

  • y is an animated value representing the vertical scroll position.

  • index is the index of the item being rendered.

const AnimatedItem = ({ propitems, y, index }) => {
const translateY = Animated.add(
y,
y.interpolate({
inputRange: [0, index * ITEM_HEIGHT],
outputRange: [0, -index * ITEM_HEIGHT],
extrapolateRight: "clamp",
})
);
return (
<Animated.View
style={[
styles.item,
{ transform: { translateY } },
]}
key={index}
>
<Item color={propitems.color} text={propitems.text} />
</Animated.View>
);
};
export default AnimatedItem;
  • Line 1: We define the AnimatedItem component.

  • Lines 2–9: The translateY value is calculated using Animated.add to add the y value with another interpolated value. The interpolation is based on the index and ITEM_HEIGHT. The extrapolateRight property is set to "clamp", which means that any values outside the defined range will be clamped to the edge of the range.

    • Line 4: The interpolate method maps input ranges to output ranges.

    • Line 5: inputRange defines the range of values that the animated value y is expected to take. In this case, it’s from 0 to a slightly higher value, which is influenced by the index and ITEM_HEIGHT.

    • Line 6: outputRange defines the corresponding output values for the specified input range. This will mean that as the y value increases, the output will decrease, creating a downward motion.

    • Line 7: extrapolateRight: "clamp" ensures that when the animated value y goes beyond the specified input range, it clamps the output to the last value in the output range. This prevents unwanted artifacts or unexpected behavior when scrolling.

  • Lines 11–16: This component returns an Animated.View with styles that include a transform property with translateY. This will cause the view to animate its vertical position based on the calculated translateY value.

  • Line 17: Each AnimatedItem is assigned a key prop with the value of index. This is important in React for efficient rendering and identifying each item uniquely in a list.

  • Line 19: The Item is rendered in the Animated.View. It receives two props, color and text, which are extracted from the propitems prop.

  • Line 24: Finally, the AnimatedItem component is exported as the default export.

Creating the list

Now that our animated item has been created, we can now work on creating a FlatList and populating it with data. Let’s see how this is done in code.

import React from "react";
import { Animated, FlatList } from "react-native";
import AnimatedItem from "./AnimatedItem";
const AnimatedFlatList = Animated.createAnimatedComponent(FlatList);
const colors = [
"#FF99A1",
"#FFCC66",
"#FFFFB3",
"#B3FF99",
"#99C2FF",
"#E0CCFF",
];
const data = Array.from({ length: 10 }, (_, index) => ({
key: `item${index}`,
text: `Item ${index + 1}`,
color: colors[index % colors.length],
}));
const MyAnimatedList = () => {
const y = new Animated.Value(0);
const onScroll = Animated.event(
[{ nativeEvent: { contentOffset: { y } } }],
{
useNativeDriver: false,
}
);
const renderItem = ({ index, item }) => (
<AnimatedItem propitems={item} y={y} index={index} />
);
return (
<AnimatedFlatList
scrollEventThrottle={1}
showsVerticalScrollIndicator={false}
data={data}
renderItem={renderItem}
keyExtractor={(_, index) => index.toString()}
{...{ onScroll }}
/>
);
};
export default MyAnimatedList;
  • Lines 1–3: We import the necessary libraries, and our AnimatedItem in the first three lines of the code.

  • Line 5: The Animated.createAnimatedComponent() method is used to create an animated version of a FlatList component. This will allow us to animate the FlatList component using the capabilities provided by the Animated module, such as animating its position, opacity, scale, etc.

  • Lines 7–14: We create an array of colors that we will use to color each item of the list.

  • Lines 16–20: The data array of size 10 is created. We create the key, text and set the color. These are properties that we will use to create our list of items.

  • Lines 22–23: We create a functional component, MyAnimatedList. Inside this component, we set up an animated value y using Animated.Value(0). This value will be used to track the vertical scrolling position of the AnimatedFlatList.

  • Lines 24–29: The onScroll constant is created using Animated.event(), which is a helper function for creating event handlers that update animated values. It listens for scroll events on the AnimatedFlatList and updates the y value accordingly. useNativeDriver is a boolean option that determines whether the animation should be executed on the native thread or not. We set this to false for better compatibility.

  • Line 30: The renderItem function is defined to render each item of the list using another component called AnimatedItem, passing in the y value and the item’s index as props.

  • Lines 34–43: The MyAnimatedList component returns an AnimatedFlatList component, passing in the props, including data, renderItem, keyExtractor, and onScroll. This AnimatedFlatList is essentially a regular FlatList but with added animation capabilities controlled by the y value and the scroll events tracked by onScroll.

  • Line 46: Lastly, we export MyAnimatedList as default.

Scrolling in action

Let’s see the progress we have made so far. The widget below contains the code for the Item, AnimatedItem, and AnimatedList components, along with some simple boilerplate code in the App.js file.

import React from "react";
import { View, Text } from "react-native";

export const ITEM_WIDTH = 360;
export const ITEM_HEIGHT = 180;

const Item = ({ color, text }) => {
	return (
		<View
			style={{
				width: ITEM_WIDTH,
				height: ITEM_HEIGHT,
				backgroundColor: color,
				borderRadius: 20,
				justifyContent: "center", // Center the text vertically
				alignItems: "center", // Center the text horizontally
			}}
		>
			<Text
				style={{
					color: "black",
					fontSize: 30,
					fontFamily: "Helvetica",
				}}
			>
				{text}
			</Text>
		</View>
	);
};

export default Item;
Basic scrolling implementation

Implementing the animations

Now that the list scroll has been animated, we can focus on adding opacity and scale effects to the items. To create the bubble-in and bubble-out effects, we need to modify the scale of the items based on their current scroll positions. Since we have already made the effort earlier, this should be a simple process now.

import { Dimensions } from "react-native";
const { height: height } = Dimensions.get("window");
const isDisappearing = -ITEM_HEIGHT;
const isTop = 0;
const isBottom = height - ITEM_HEIGHT;
const isAppearing = height;
const scale = position.interpolate({
inputRange: [isDisappearing, isTop, isBottom, isAppearing],
outputRange: [0.5, 1, 1, 0.5],
extrapolate: "clamp",
});
const opacity = position.interpolate({
inputRange: [isDisappearing, isTop, isBottom, isAppearing],
outputRange: [0.5, 1, 1, 0.5],
});
  • Lines 1–2: We begin by first getting the height of our output window using Dimensions module from the react-native library. The height property is then extracted from the object returned by Dimensions.get("window").

  • Lines 4–7: To make the process easier, we can create a few constants, which are as follows:

    • isDisappearing is set to -ITEM_HEIGHT. It represents the point where an item is completely scrolled out of view above the list.

    • isTop is set to 0. This is the top of the list where an item is fully visible.

    • isBottom is calculated as height - ITEM_HEIGHT. This is the point where an item is fully visible at the bottom of the list.

    • isAppearing is set to height. It represents the point where an item is completely scrolled out of view below the list.

  • Lines 9–13: We use the interpolate method to scale the items in the list based on their vertical position. We set the inputRange as the constants defined earlier. Our outputRange scale is set to 0.5 when the item is disappearing or appearing and 1 when it is fully visible at the top or bottom of the list.

  • Lines 15–18: A similar approach is used for both scale and opacity in this case.

Complete code

Let’s see what our animated list looks like with the opacity and scale animations applied.

import React from "react";
import { View, Text } from "react-native";

export const ITEM_WIDTH = 360;
export const ITEM_HEIGHT = 180;

const Item = ({ color, text }) => {
	return (
		<View
			style={{
				width: ITEM_WIDTH,
				height: ITEM_HEIGHT,
				backgroundColor: color,
				borderRadius: 20,
				justifyContent: "center", // Center the text vertically
				alignItems: "center", // Center the text horizontally
			}}
		>
			<Text
				style={{
					color: "black",
					fontSize: 30,
					fontFamily: "Helvetica",
				}}
			>
				{text}
			</Text>
		</View>
	);
};

export default Item;
Complete code for the application

Our list is animating beautifully with React Native’s Animated API. You can feel free to customize the animations and play around with the visuals. The options are limitless!

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved