DEV Community

Mazahir
Mazahir

Posted on

How to create Animated FlatList in React-Native

Hey guys, I am Mazahir.
Today we are gonna learn how to use Animated API with FlatList to create
beautiful animations.

Requirements

  • Latest version of expo and react-native installed
  • Basic of expo with typescript
  • Nothing else, Let's get started

Preview

Before we get our hands dirty, let's see what are we trying to make.
react-natve animated flatlist

Your project will end up looking like this.

Initialization

  • Create a new expo project

expo init -t expo-template-blank-typescript

  • After Creating a new project, We need some data to display. I am using faker to create fake data but you can use an API or Hard Coded data as well.

How to create fake data using faker

  • npm i faker
  • Paste this code snippet. ```

// Inside App.tsx
const fake : string[] = new Array(20).fill('test');
const data: data[] = fake.map(() => ({
name: faker.name.findName(),
job_title: faker.name.jobTitle(),
email: faker.internet.email(),
key: faker.random.alphaNumeric(10),
avatar: faker.image.avatar(),
}));

 * I am using **react-native-paper** for styling. Its not  necessary for you to install, but I highly recommend it.

`npm i react-native-paper`

## FlatList & Animations

* To create beautiful animations like I said, We first need a FlatList. Create a folder named components and add a file named list.tsx.


* Add the required import statements.

Enter fullscreen mode Exit fullscreen mode

// inside components/list.tsx
import * as React from "react";
import { Text, View, StyleSheet, Animated, Dimensions } from "react-native";
import { Avatar, Surface } from "react-native-paper";

const { height } = Dimensions.get("screen");

_I am getting the height of the screen as well, which will be useful later_

* Now, we will create a basic function and a normal flatlist

Enter fullscreen mode Exit fullscreen mode

interface Data {
name: string;
email: string;
job_title: string;
key: string;
avatar: string;
}

export default function List({ data }: { data: Data[] }) {
return (

data={data}
keyExtractor={(item) => item.key}
renderItem={({ item, index }) => {

      return (
        <Animated.View>
          <Surface style={styles.surface}>
            <View style={{ flex: 0.3, justifyContent: "center" }}>
              <Avatar.Image size={42} source={{ uri: item.avatar }} />
            </View>
            <View
              style={{
                flex: 0.7,
                flexDirection: "column",
                justifyContent: "center",
              }}
            >
              <Text style={{ fontSize: 22, fontWeight: "bold" }}>
                {item.name}
              </Text>
              <Text style={{ fontSize: 14 }}>{item.job_title}</Text>
            </View>
          </Surface>
        </Animated.View>
      );
    }}
  />
</View>
Enter fullscreen mode Exit fullscreen mode

);
}

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
},
surface: {
height: height * 0.1,
marginTop: 15,
padding: 8,
marginHorizontal: 10,
borderRadius: 8,
flexDirection: "row",
},
});

_Even if i add Animated.FlatList or Animated.View, it will work as normal View and FlatList._

### Animations

* Inside list.tsx, Create a ref for an animated value
`const scrollY = React.useRef(new Animated.Value(0)).current;`
_This will store the scroll offset of the Flatlist._

* To update the *scrollY*. 
Enter fullscreen mode Exit fullscreen mode

onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: scrollY } } }],
{ useNativeDriver: true }
)}

_Here we assign y offset of the list to our ref, useNativeDriver is true, that's something we don't need to worry about right now_

* if you save the changes, everything should work fine but there are no animations.

 1. to animate list we need 2 things *input range* and *output range*
 2. You can think of input range and output range as key frames if u know what that means.
 3. To define it input range is a set of values at which you want to animate or change a value.
 4. Output range is set of values that react or change based on the input range.
 _It's okay if u did not understand it._

* Enough theory let's get some animation on the screen.
 Inside the renderItem function we will add
Enter fullscreen mode Exit fullscreen mode

const inputRange = [
-1,
0,
(height * 0.1 + 15) * index,
(height * 0.1 + 15) * (index + 3),
];

height * 0.1 because that the height of the item or the view according to the style, we add 15 because of the margin.

when the content offset is at -1 or 0 we don't want any changes to the view or item, but we want to start the animation as soon as the item touches the top and the animation to end when the 3rd element( 3rd element from the current item) touches the top.

* Now to animate the opacity
Enter fullscreen mode Exit fullscreen mode

const opacity = scrollY.interpolate({
inputRange,
outputRange: [1, 1, 1, 0],
});

we store the animated value in const opacity. scrollY.interpolate it takes 1 argument an object with 2 array the input range and the outputrange.

* We also need to translateX or to move the view on the x-axis. so we create interpolated value.
Enter fullscreen mode Exit fullscreen mode

const Offset = scrollY.interpolate({
inputRange,
outputRange: [0, 0, 0, 500],
});


* That's it, We have all the values we need. The only thing left to do is just wire them up.
Enter fullscreen mode Exit fullscreen mode

style={{
transform: [{ translateX: Offset }],
opacity: opacity,
}}
>

if save the changes, You should have working animations. if you got an error or the code does not work then you can check it with the my completed code [here](https://github.com/Mazahir26/react-native-animated-flatlist)

* You can play around with the input range and output range
and get different results

## Conclusion
Animation in react native is pretty simple if you know what you are doing.

You can find the completed code  [here](https://github.com/Mazahir26/react-native-animated-flatlist)

I hope you enjoyed and learned something out of this.
Any suggestions or feedback would be awesome. :)

Thank you.







Enter fullscreen mode Exit fullscreen mode

Top comments (0)