The Rive engineering team’s a fan of Flutter; so much so that we used it to rebuild the Rive editor, which we currently deploy to web and MacOS, with more platforms on the way.
While most of our runtimes use a shared C++ core, the Flutter runtime does not. It shares the editor’s rendering core, allowing us to maintain a single Flutter-based renderer written in Dart. It also has a different API style, more in keeping Flutter’s widget pattern. The runtime’s available in pub and Github.
Let’s dive into the runtime, explore how to play animations, and how to mix them in code.
Playing Rive animations in Flutter
In this first example we’ll take a spin in a monster truck. The truck.riv file contains 4 animations: idle, bouncing, windshield_wipers, and broken. These are designed to be mixed together to create sophisticated behavior, but let’s start simple and animate the truck in its idle state.
We’ll add the rive package, and truck.riv to pubspec.yaml:
Here’s the code in its entirety. It loads a Rive file, initializes and plays the idle animation.
We’ve created a widget, MyRiveAnimation, which is stateful because we load in the Rive file directly inside the widget, and we only want to load once on initialization. Note that we load raw bytes. This gives you flexibility in where you source your Rive data: as assets, over a network, from a local database, or by other means.
Once the data is imported into a RiveFile, we can access any of the file’s artboards and play the animations they contain. In our truck example, there’s one artboard, so we can fetch that with the file.mainArtboard property.
We attach RiveAnimationControllers to artboards that will give us control of how the artboard’s animations are played and mixed. Here we use a basic animation controller -- SimpleAnimation -- that comes with the rive package. The controller auto-plays the specified animation.
We use the Rive widget to render animations. This widget takes an artboard and an optional fit parameter.
And that’s it; the idle animation should now be playing in your app. If you want to see the other animations, simply swap out idle for bouncing, or windshield_wipers.
Mixing Rive animations
What if you wanted to play multiple animations at the same time?
One of Rive’s strengths is its ability to mix animations together and to independently control animation playback through code. Let’s see how we can get both idle and windshield_wipers animating concurrently:
Much of this code remains unchanged. The primary difference is that there are now two SimpleAnimation controllers: one for the idle animation and is always running, and one for windshield_wipers, that can be started and stopped.
The Switch widget fires _wipersChange, which creates the wipers controller the first time it's run, and starts or stops the animation by setting isActive on the controller. When both animations are playing, they’re mixed together; note how the wiper movement is blended with the bouncing motion of the truck.
Customizing animation control
When playing the windshield_wipers animation, you can see how the truck’s wipers will pause as soon as you hit the switch. What if we don’t want our wipers to get in the way of our view when they’re not active and instead return to their start state?
Animation controllers let us customize animation behavior at runtime. windshield_wipers is a loop animation, meaning it will repeatedly play from beginning to end while active. There are two other animation modes: oneShot plays the animation from beginning to end, and then stops; pingPong will play an animation from beginning to end and then end to beginning repeatedly.
Lets introduce our own WiperAnimationController to control our animation:
WiperAnimation extends SimpleAnimation and provides two new functions: stop flips the animation loop mode to oneShot, meaning that the animation will complete and stop, rather than looping indefinitely; start sets the loop mode back to loop and reactivates the animation.
But what disables the animation with stop? The SimpleAnimation controllers apply function takes care of that by deactivating animations that have completed.
Now that we have our WiperAnimation controller we can use it instead of the SimpleAnimation controller in our app:
Take the truck for a spin and watch the wipers, you’ll notice that the wiper animation now completes its animations if it’s toggled to stop.
That’s it for part one; we’ve just scratched the surface of what can be done with animation controllers and mixing. In part 2 we’ll take our truck off-road and cover programmatically controlling animation speed and more advanced ways to mix animations.