Customize Hero Animation in Flutter (Part 2)

TheBoringDeveloper
Level Up Coding
Published in
5 min readDec 22, 2019

--

Welcome to this tutorial for Customizing Hero Animation in Flutter — Part 2.

Check out part 1 to see a different hero animation implementation.

You can connect with me on Instagram

Let’s start by seeing our end goal

Now let's see what is happening:

  1. On button click, we navigate from Screen1 to Screen2
  2. During screen navigation, the stars are animated to a new position using a Hero widget

Here is the starter code:

The output of the above code:

Now let's add the hero widget

Here we need to add the Hero widget around each star icon

children: List.generate(5, (index) {
return Hero(
tag: 'ratingStar',
child: Icon(
index < rating ? Icons.star : Icons.star_border,
color: kCoolOrange,
size: size,
),
);
}),

Let's check the output now:

We have a problem.

Let's check the console-

So it looks like the tags share the same tag name in a sub-tree.

Let's try to assign each hero a different tag.

children: List.generate(5, (index) {
return Hero(
tag: 'ratingStar$index',
child: Icon(
index < rating ? Icons.star : Icons.star_border,
color: kCoolOrange,
size: size,
),
);
}),

Now the tag names will be ratingStar0, ratingStar1, ratingStar2, ratingStar3, ratingStar4.

Let's check the output:

However, we cannot see the transition properly so let's slow it down.

We will make the following update

Navigator.push(
context,
PageRouteBuilder(
transitionDuration: Duration(seconds: 2),
pageBuilder: (_, __, ___) => Screen2(),
),
);

It slows down the page transition.

Let's check the output now:

Look’s good but isn’t exactly what we what.

What do we want?

  1. We want the stars to start quickly and then slow down
  2. The stars to the left side should faster slower than the right one

Let's solve this

You can skip this section if you check out my previous blog here

Now first let's see the properties of the Hero widget-

createRectTween → Defines how the destination hero’s bounds change as it flies from the starting route to the destination route.

As the hero flies, its rectangular bounds are animated using Tween<Rect>, specified in Hero’s createRectTween property. By default, Flutter uses an instance of MaterialRectArcTween, which animates the rectangle’s opposing corners along a curved path.

flightShuttleBuilder → Optional override to supply a widget that’s shown during the hero’s flight.

placeholderBuilder → Placeholder widget left in place as the Hero’s child once the flight takes off.

From the above definitions, we can conclude that

We can solve this problem by providing our own implementation of createRectTween

Add this method in RatingBar class:

static RectTween _createRectTween(Rect begin, Rect end) {
return CustomRectTween(begin: begin, end: end);
}

Let's implement this class:

class CustomRectTween extends RectTween {
CustomRectTween({Rect begin, Rect end})
: super(begin: begin, end: end) {}

@override
Rect lerp(double t) {
//Add implementation here
print(t); //Returns value from 0.0 to 1.0.
}
}

Now we need to return a Rect from lerp(double t), which specifies the position and bounds of the hero.

We will return Rect using:

return Rect.fromLTWH(left, right, width, height);

We will provide the left and right to the animate path.

The begin and end Rect parameters contain information about the widgets before and after the Hero animation.

double height = end.top - begin.top;
double width = end.left - begin.left;

Here we are calculating the difference in height and width before and after transition completion.

In our case, the width wouldn’t change as we are moving vertically only.

The value of t linearly increases from 0 to 1.

Lets change the lerp() function:

Let's check the output:

This seems to work exactly the same as the default animation the animation is moving at a constant.

IMPORTANT: To change translation we need to change the way t changes values.

We can see in the above graph that the Curves transform a given value of t to a new value.

We can use this to change the way translation is done.

In the above code, we only use Curve on y axis for transformation to a new value.

Let's see the output:

Let's try out some other curve

Let's check the output:

We have solved the first problem as the stars now start quickly and then slow down.

Let's solve problem 2

The stars to the right should move slower than the left one

Now let's modify our code, such that it uses different Curves for different stars.

We are assigning a Curve based on index.

Let's check the output:

The complete code is available here.

Thank you for staying until the end.

I will be posting more about flutter, so stay tuned :)

--

--