Material Design Motions with React Native — Hello world
Ever since material design motion guidelines were unveiled in Google I/O, I became a huge fan of it. I always wanted to code these beautiful animations.
However, despite the great advantages of using react-native, the first step can be a bit daunting. That’s why I’ve started writing a series of posts (more like a journal) that take you step-by-step through coding almost all the material design motion implementations presented in their guidelines.
- Chapter 1: Hello World
Anatomy of the transition
Before we write a single line of code, let’s break down the animation into phases and study each one in detail.
- Scene 1: Initial state when the user presses the FAB button.
- Scene 2: The FAB button moves to the bottom and the icon fades away
- Scene 3: In the next instant the FAB button expands to fill the container and menu buttons slowly starts to fade in
- Scene 4: Once the FAB button has filled up the space and menu buttons have appeared.
- Scene 5: The menu buttons expand slightly to fill up the space to give the reveal effect.
Thus the entire animation sequence can be defined with the help of just four points in the range of 0 to 1.
0: representing the start of the animation sequence
MOVE_END: representing animation progress where FAB button has moved to the bottom and icon has faded away
TRANSFORM_END: representing animation progress where FAB button has expanded and menu buttons have faded in.
1: representing end of animation sequence
Talk is cheap. Show me the code
Enough with the explanation. Lets get our hands dirty.
Creating the FAB
To create Floating action button or commonly known as FAB, let’s start by creating a simple view and apply some styles as specified in the material design guidelines.
To make the FAB button touchable, let’s wrap it up with a TouchableNativeFeedback in case of Android and TouchableOpacity in case of iOS.
Creating animation sequence
Lets start with creating an animated value which changes from 0 to 1 (in case of reveal menu transition) and 1 to 0 (in case of hide menu transition). Lets also fix the MOVE_END value to 0.2 and TRANSFORM_END value to 0.6. (These values are arbitrary and you can play with them until you get the perfect animation sequence).
In the move phase, the FAB button moves from the bottom right position to the bottom of the screen in a curve path.
To move the FAB from the initial position to the final position, we interpolate the value of animationProgress with inputRange being [0, MOVE_STOP, TRANSFORM_STOP, 1] and outputRange being [INITIAL_FAB_POSITION_RIGHT, FINAL_FAB_POSITION_RIGHT, FINAL_FAB_POSITION_RIGHT, FINAL_FAB_POSITION_RIGHT]. The last three value repeats to make sure that even though the animationProgress value changes greater than MOVE_STOP point, the FAB’s right position never changes. Similarly the FAB’s bottom position and icon’s opacity are also changed.
To move the FAB in a curvilinear path, we use easing while interpolation. A point moves in straight line if both the vertical and horizontal position changes uniformly. But if we add easing while interpolating the vertical position it would move in a curvilinear path.
In the transform phase, the circular FAB button transform into a rectangular toolbar. This effect can be achieved by wrapping the FAB with a container which has overflow hidden to clip the circular shape of FAB. And instead of moving the FAB button we now need to move the container.
Initial the container would be enclosing the FAB button (with some additional padding to prevent clipping the button’s shadow). Once the move phase is completed, the FAB button would scale up and the container would change its shape from a square to rectangle, giving the nice and smooth fill effect.
Reveal Toolbar Menu
Toolbar menu is revealed in two phases. During the transform phase, its opacity is changed from 0 to 1. And once the transform phase is completed its scale is changed from 0.95 to 1.
The above implementation is just the beginning. It can be obviously optimized and componentized. In the next blog we would looking on how to use improve performance and create reusable components.
You could check the implementation using Expo.
Feel free to suggest any changes you think should be added.