Performance-based animation and animation example in Flutter

Abdullah Dundar
Codimis
Published in
5 min readFeb 24, 2023

Hi everyone. There are some things we need to pay attention to while we are in the mobile application development phase. The performance of the application is one of the conditions to be considered. We know that Flutter technology allows us to design fast UIs and animations. So how can we use these animations in the most efficient and functional way?

In this article, I will try to explain and show you this with examples.
So let’s get started…

Flutter Skia engine and widgets provide maximum performance to users by creating and throwing quickly. The only thing left to the developers will be to avoid common mistakes. If the animations seem jerky when we first run our mobile application, it is because of ‘shader compilation’. The long-term solution to this is Impeller for iOS. Impeller does not work well on Android devices as it depends on the device and GPU it is running on.

What is “Shader compilation jank”?

Shader is a piece of code that runs on the GPU. When Skia sees a graphic drawing for the first time, it creates and compiles the GPU Shader for that script. This Shader allows the animation in question to quickly generate potentially similar sequences. Skia’s Shader takes a few hundred milliseconds to compile, while a 60fps image needs to be drawn in 16 milliseconds. So this build may cause 60fps to drop to 6fps. This is “compilation jank”. The animation should work fine after this build is complete. On the other hand, applications running on “Impeller” have all the Shaders they need and can be used without janking animations.

Technically, these are factors in the performance of animations. The developer’s job is to advance animation development in accordance with flutter’s documentation. So how should we proceed in this part?

As an example, let’s choose an animation according to our needs from a diagram provided to us by flutter, for example, implicit animation. If we talk about these animations, implicit animations allow us to add motion and visual effects to our UI. They are structures that Flutter offers ready to use for us. For example, in the text effect Fade, AnimatedOpacity etc.

Let’s make a sample animation!

As seen above, we can follow a way to change our AnimatedContainer. First, let’s create an AnimatedContainer that changes border, height, width and color.

  AnimatedContainer(
width: sizes[index],
height: sizes[index],
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(radius[index]),
color: colors[index],
boxShadow: [
BoxShadow(
color: Colors.black54,
blurRadius: radius[index],
),
],
border: Border.all(
color: bColors[index]!,
width: index * 10.0,
),
),
duration: kThemeAnimationDuration,
curve: Curves.easeInOut,
child: InkWell(
onTap: () {
setState(() {
setIndex();
});
},
child: Center(
child: AnimatedDefaultTextStyle(
duration: kThemeAnimationDuration,
style: TextStyle(fontSize: tSizes[index]),
child: Text(
anmatdCntanr,
textAlign: TextAlign.center,
),
),
),
),
),

As you can see, every time it is pressed, it changes the properties I mentioned depending on the parameters, causing our animation to occur. So how do we set it to change every time we click, and according to what? In the viewmodel class of this view page we created, the following variables and setIndex(); We need to create our function.

Alignment alignment = Alignment.center;
String anmatdPhysclMdl = "AnimatedPhysicalModel";
String anmatdCntanr = "AnimatedContainer";
int index = 0;
final colors = [Colors.green, Colors.deepPurple, Colors.red];
final bColors = [Colors.transparent, Colors.purple, Colors.green[800]];
final sizes = [150.0, 195.0, 300.0];
final tSizes = [12.0, 16.0, 20.0];
final radius = [0.0, 16.0, 90.0];
final elevations = [0.0, 16.0, 32.0];
final opacity = [1.0, 0.3, 0.01];


void setIndex() {
index = (index + 1) % colors.length;
}

You can customize it in a different way as well.

We can also obtain the text with the changed Opacity under our container as follows;

   Padding(
padding: const EdgeInsets.only(top: 20),
child: AnimatedOpacity(
opacity: opacity[index],
duration: kThemeAnimationDuration,
child: InkWell(
onTap: () {
setState(() {
setIndex();
});
},
child: Padding(
padding: const EdgeInsets.all(32.0),
child: Text('AnimatedOpacity ${opacity[index]}'),
),
),
),
),

We can ensure that the opacity of the text we give to the View screen in this way changes and different attributes depending on you change. When it is pressed, setIndex(); You can make changes using the function.

We can create our TextButton at the bottom, which goes to a different place as you click, with the following codes on our view screen.

 SizedBox(
height: 400,
child: Stack(
children: [
AnimatedAlign(
duration: kThemeAnimationDuration,
alignment: alignment,
child: TextButton(
onPressed: () {
setState(() {
randomFunction();
});
},
style: TextButton.styleFrom(
textStyle: const TextStyle(fontSize: 24)),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text('AnimatedAlign $alignment'),
),
),
),
],
),
),

So how do we control the action it takes as it clicks? randomFunction() used here; function is as follows.

void randomFunction() {
final random1 = (math.Random().nextDouble() - 0.5);
final random2 = (math.Random().nextDouble() - 0.5);
alignment = Alignment(random1, random2);
}

Thanks to this function, we assign the randomly generated values to the alignment value used in our widget. Thus, when we click on our widget, we can observe the displacements.

You can also look at the sample codes from the flutter_with_animations repository on my GitHub profile (https://github.com/abdullahD00) and follow me. Thank you for reading. I hope I was able to explain the issue. If you like my article and want to be informed about my articles that I will share later, you can follow me. You can reach us via e-mail and LinkedIn.

--

--

Abdullah Dundar
Codimis
Writer for

I am student of Computer science. I am currently developing SAP&ABAP and ı do things what ı enjoy.