Customize Hero Animation in Flutter (Part 2)
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:
- On button click, we navigate from Screen1 to Screen2
- 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?
- We want the stars to start quickly and then slow down
- 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 :)