Let’s Get Moving: An Introduction to React Native Animations — Part 1
When I first got into writing apps in React Native, I had visions of modern and dynamic layouts with awesome animations. Sometimes, however, you get so fixated in making the dang thing work the way you want to you just never get around to figuring out how to get the proverbial animated icing on the cake.
In this series I will introduce the basic concepts I’ve picked up on how to get your App moving in the ways you want to as quickly as possible.
Caveat: This article assumes you know the basics of react
/ react-native
and have the react-native
cli tools installed. For more information on that you can read the docs here.
Part One: LayoutAnimation
Open up your terminal and let’s get started with a basic app.
react-native init Animations
cd Animations
react-native run-ios
If you’re still with me, you should see something like this:
Most of what we’re going to do here is going to happen inside App.js
for simplicities sake. So open that up in your browser of choice and clear out everything except the basic boilerplate. Import Image from 'react-native’
and drop one inside the container view. For this example I’m using this png of Jake from Adventure Time and just placing it in the root of the project. I’ve also added some top and bottom padding to the container to avoid the notch and menu bar at the bottom:
// App.jsimport React, { Component } from "react";
import { StyleSheet, Image, View } from "react-native";
import jake from "./jake.png";export default class App extends Component { render() {
return (
<View style={styles.container}>
<Image source={jake} />
</View>
);
}
}const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#F5FCFF",
paddingTop: 64,
paddingBottom: 32
}
});
LayoutAnimation
is React Native’s most basic animation system. Anytime the view is going to re-render, causing elements to change their position/size/rotation/etc, running LayoutAnimation.[easingFunction]
before the re-render will cause those differences in layout data to be animated.
Let’s assign the vertical positioning rule on our container (which currently only includes Jake) to a piece of state in our component:
// App.js{...}class App extends Component {
constructor(props) {
super(props);
this.state = { position: "flex-start" };
}render() {
return (
<View style={[styles.container, { justifyContent: this.state.position }]}>
<Image source={jake} />
</View>
);
}
}{...}
Now lets just create some buttons that update that position.
Import Button
from react-native
and add some to your render
method:
// App.jsrender() {
return (
<View style={[styles.container, { justifyContent: this.state.position }]}>
<Image source={jake} />
<View style={styles.buttonsContainer}>
<Button style={styles.button} title="Top" />
<Button style={styles.button} title="Middle" />
<Button style={styles.button} title="Bottom" />
</View>
</View>
)
}{...}
buttonsContainer: {
flexDirection: "row",
justifyContent: "space-evenly",
position: "absolute",
bottom: 16,
width: "100%"
},
button: {
width: 100
}
{...}
Now we will create a method to change the `justifyContent` value on the icon and apply it to the buttons we created with the appropriate argument:
// App.js{...}changePosition = position => {
this.setState({
position
});
};{...}<View style={styles.buttonsContainer}>
<Button
style={styles.button}
title="Top"
onPress={() => this.changePosition("flex-start")}
/>
<Button
style={styles.button}
title="Middle"
onPress={() => this.changePosition("center")}
/>
<Button
style={styles.button}
title="Bottom"
onPress={() => this.changePosition("flex-end")}
/>
</View>{...}
Our buttons now instantly change the positioning of the icon.
Now, since this is a simple layout change, and the only thing really going on with these re-renders, it’s a perfect candidate for using RN’s LayoutAnimation API. Simply import LayoutAnimation from "react-native"
and run it before setting your new state.
Note that in order to get this to work on Android you need to set the following flags via UIManager
which is also imported from react-native
: UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true);
// App.jsUIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true);{...}changePosition = position => {
LayoutAnimation.spring();
this.setState({
position
});
};{...}
LayoutAnimation
provides us with three easing presets spring
, linear
, and easeInEaseOut
. Custom configurations can be make, but I’m not going into that here. You can read more about what’s happening under the hood with LayoutAnimation
here.
LayoutAnimation.spring()
is a shortcut for the more verbose LayoutAnimation.configureNext(LayoutAnimation.Presets.spring)
.
Refresh your app, and now you should see Jake move with a pleasant springy movement!
The final code can be found here.
Hopefully this was a pretty painless introduction to getting things moving in your React Native apps. In the next part we will go into more granular control over our animations.
📝 Read this story later in Journal.
🗞 Wake up every Sunday morning to the week’s most noteworthy Tech stories, opinions, and news waiting in your inbox: Get the noteworthy newsletter >