Fluid Transitions with React Navigation
Introduction
When navigating in a mobile app you’ve probably already experienced how each new page is usually moved in above the current page with a nice animation. In modern apps these animations are often replaced with a more fluid transition where elements on screen appears to be morphed into the next screen — creating the notion of a more dynamic user experience.
In React Native it can be hard to implement fluid and dynamic user experiences without writing a lot of special case code that can be hard to maintain and reuse.
Navigation in React Native
I started with the popular navigation library React Navigation — a well designed library for building all sorts of navigation setups and although it can be a bit complex to set up (especially if you’re using Redux), it has matured over the years to be one of the go-to libraries when it comes to navigation and React Native.
To build fluid user experiences with React Navigation I built React Navigation Fluid Transitions - a library that gives you a few simple building blocks that can be used to control individual transitions for your UX elements during navigation as an add-on to React Navigation.
Example time
Let’s show a simple example where we build an onboaring flow with React Navigation and the React Navigation Fluid Transitions library.
We’ll start with the on-boarding screens where we present our fantastic app to our users.
Let’s build the main interface for our on-boarding flow, style it and connect everything together with a StackNavigator to enable navigation. The example consists of the round logo component and two on-boarding screens.
Adding Fluid Transitions
Wouldn’t it be nice if we could add a shared transition between the two logos so that the user would perceive a connection between these two elements?
Adding shared element transitions requires you to add the React Navigation Fluid Transition library to your project:
yarn add react-navigation-fluid-transitions
The library offers a new stack-based navigator supporting shared element transitions and more (have patience — we’ll get to the more part later). Let’s import and swap out the StackNavigator for the FluidNavigator component.
Start by importing the FluidNavigator and the Transition component:
import { FluidNavigator, Transition }
from ‘react-navigation-fluid-transitions’;
Now you should be able to change from the regular StackNavigator to the FluidNavigator:
const Navigator = FluidNavigator({
screen1: {screen: Screen1},
screen2: {screen: Screen2}
});
Shared Element Transitions
Now we are ready to add some shared element transitions between the two logos. Wrap the logos in a Transition element and give them the same value for the shared property and run your sample again:
<Transition shared=”logo”>
<LogoImage style={styles.largeLogo}/>
</Transition>...<Transition shared=”logo”>
<LogoImage style={styles.smallLogo}/>
</Transition>
You should now be able to see the transition between the two logos when navigating from the first to the second screen:
Transitions (the more part)
You may have noticed that the text is only faded in/out during the navigation transition. This is because there are no shared text elements between the two pages (text is different so it would look strange). It would be nice if we could add some transitions to make the text take part in the transition as well.
Let’s see how we can use the Transition element to add transitions to the text elements:
<Transition appear=”horizontal”>
<Text style={styles.paragraph}>
Welcome to this fantastic app!
</Text>
</Transition>
Repeat this for all the other text elements in your code (note that each Transition element can only contain one child).
Now run the example and enjoy:
The React Navigation Fluid Transitions library has a list of predefined transitions that can be used, and it is also easy to add your own transitions by providing custom transition functions. You can read more about how to do this and the different transitions in the documentation.
Test and see the final results of this article on expo:
Further Articles
You can read about implement a more complex example here:
https://medium.com/@christian.falch/react-native-animation-challenge-1-7022e48a226
Conclusion
Using the React Navigation Fluid Transitions library lets you declare how individual elements are transitioned during a navigation transition. Support for shared element transitions and a highly customizable yet simple way to set up transitions should provide you with the building blocks needed for building a dynamic and engaging user experience.
Limitations
The library uses the native animation driver on both Android and iOS to get full 60 fps performance. Custom transitions trying to animate properties that are not supported by the native animation driver will not work (although it is possible — but not recommended — to configure the navigator not to use the native driver).
Shared element transitions animate position and scaling of elements, so each element taking part in a transition should have the same aspect ratio and content.
Notes
The library was originally inspired by a pull request and a series of articles by Linton Ye on the topic of shared element transitions in React Native. Some of the code is inspired by his ideas and his original implementation. The React Navigiation team also has an open RFC request for the topic.