Flutter flip coin animation test-drive

Pyts Mike
4 min readJun 16, 2019

--

Some time ago I was surfing through the pages searching for the news about Google Fuchsia and decided to check if Flutter is really alternative for React Native and what is all that magic atmosphere around it. Also, I had in plans to switch from Android Native to cross-platform development, so it was the right time to try it out.

Google Trends for most popular cross-platform frameworks

This article describes how to implement:
- Animation Builder and Animation controller for Staggered Animation
- Transform and Matrix4 for widgets transformations

Widgets used:
Tweens, Animated Builder, Column, Stack, Expanded, SizedBox, GestureDetector, Transform, Matrix4, Material, ShaderMask, Icon, Animated Controller, Future async/await

As usual, couple of codelabs were checked and official documentation was sniffered, I have experimented a bit with everything and decided to build realistic (at least similar to physical model) flip coin animation:

It consists of three main parts:
1. Starts when you tap on Material (actually Icon wrapped within Gesture detector) and combines two actions: spinning around a vertical axis and shows throw movement by changing its elevation.
2. On the highest point (elevation = max) it blinks (as a real light model) and returns back to the start position.
3. Slowly sinks down (elevation = 0) and disappears triggering the screen door animation.

Now let’s take a look on the whole code here. It has pretty much comment and explanation for fast observation structured according to the official staggered animation documentation on Flutter page:

  • Stateless widget
  • Stateful widget

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

Stateful widget is basically screen on which you want to display the animation:

Stateful widget

Animation controller is initialized in the initState() and helps to track overall animation position (from 0.0 to 1.0 = 0% to 100%).

..addListener() which helps to identify when the animation controller reaches exact position for more sophisticated control.

reverseAndElevateDown() with async/await which is triggered when the listener receives an exact position of the controller and starts reverse flip animation, await helps to wait until animation will be finished jumping to another animation point on the timeline after.

build() just pass animation controller to the stateless Staggered Animation and receives widget to display.

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

Now let’s talk about Stateless widget a.k.a where all magic happens:

For better understanding what happens behind I have prepared mixed Gantt timeline:

Tweens intervals over whole animation controller

Tweens section — tween is a feature which allows you to use custom values (instead of using animation controller value), for example, you want to have values changing from 0 radians to 3.14 (2Pi) radians (360 degrees). Tween class has a wide variety of its members and can be used for shapes, colors, etc. As a parent, it receives animation controller from welcome screen stateful widget and also requires to set up on which timeline interval it will be used (from 0.0 to 0.1 ~ 0% to 10%, 0.5 to 0.75, etc.). Now it should give you some idea if you will check the Gantt timeline above for the second time.

build() does nothing except returning AnimationBuilder widget.
AnimationBuilder gets an animation controller and calls _buildAnimation() which is the most interest part of the widget.

_buildAnimation() is a typical Widget tree and consists of two layers (Stack widget), alongside with widgets I will explain about Tweens used in each of them and which effect they put into the whole animation.

Top layer (coin itself): Centered Material with Icon child wrapped into Transform and Gesture detector:

Material widget holds Icon and within Transform widget is rebuilt each time when flip tween value changes so it makes coin to spin around the Y axis. Probably you have noticed that I used Transform4 matrix as a transform parameter in case if some additional animation will be required instead of direct Transform widget function.

Along with flip tween size of the Icon is controlled by size tween and it makes you feel that coin is moving closer to the observer like it was thrown.

When the animation controller reaches 0.4 (40%) makes sense to show that coin is falling back to the ground. Here reverseAndElevateDown() function is triggered by the listener of animation controller, calling reverse animation, coin falls down and then animation jumps to from 0.0 to 0.5 elevating to the ground till 0.7 As a result bottom layer become the main player.

Bottom layer (door): Column which consists of two Expanded boxes and SizedBox between them:

Botton layer

The trick here is that we use mouth (don’t ask why I called it mouth and not door instead) tween to extend the height of Sized box and it’s border to imitate movement when the door (or mouth) is opened. It starts at 0.8 and lasts till the end.

All other effects like icon disappearing at the end and light blink at 0.4 works on the same logic and this article will be technically overwhelmed to represent and explain everything :)

--

--