Implicit Flutter Animations

Oct 4 2022 · Dart 2.17, Flutter 3.0, Visual Studio Code 1.7

Part 2: Implicit Animations in Action

06. Create a Custom PageView Animation

Episode complete

Play next episode

Next
About this episode
Leave a rating/review
See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 05. Animate a Social Share Button Next episode: 07. Create a Card Flip Animation

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Notes: 06. Create a Custom PageView Animation

The student materials have been reviewed and are updated as of August 2022.

The updated material uses null safety and also deploys the use coding practises encouraged by the Flutter as per the Flutter lint rules and a few addons of practises that are considered good here at raywenderlich (see analysis_options.yaml in the material for more info).

Also, the value type passed in the builder parameter of TweenAnimationBuilder is explicitly mentioned otherwise dart assumes the value as generic datatype after the release of Flutter 2.

Transcript: 06. Create a Custom PageView Animation

In this episode, we would be using implicit animations to affect how the offers slider animates. The offers slider is used inside the homescreen widget. Scroll to it then hold down the ctrl key then click on it to navigate to its file.

It is simply a PageView widget. A PageView widget creates a list of scrollable widgets which are displayed page by page. Under this widget, we have an indicator which shows the current acitve page. All this would be animated with implicit animations and after this, you’ll see that customizing in-built widget animations is quite easy. For the pageview animation, we want to make the active widget retain its size while other pageview items would be scaled down.

Now, since we’re going to be dealing with transforming the scale of pageview items, we need to select an implicit animation that would handle this. Flutter doesn’t provide an AnimatedScale widget, so we would be using the TweenAnimationBuilder to provide a custom scale animation.

In our code, the itembuilder return an Item widget which represents one pageview item. But before we do any animation, we need to way to get the selected index of the pageview. This information would be used to know which item to animate. Luckily for us, the pageview builder gives us the onPageChanged callback function which triggers whenever the page changes. Update your code to the following:

int _selectedIndex = 0;
...
onPageChanged: (index) {
    setState(() {
        _selectedIndex = index;
    });
},
...

First, we declared a variable called _selectedIndex. This variable would be responsible for holding the selected index from the pageview. Then inside the onPageChanged callback, we call setState and assigned the index returned from this callback as the value of _selectedIndex variable. With this setup, we can now keep track of the current active page in our State object.

So the next thing to do would be to wrap the Item widget with a TAB and use the _selectedIndex to trigger the animation. Go ahead and update your code to the following:

itemBuilder: (context, index) {
    final offer = offers[index];
    // New Code
    final scale = _selectedIndex == index ? 1.0 : 0.8;
    return TweenAnimationBuilder(
        duration: const Duration(milliseconds: 350),
        curve: Curves.ease,
        tween: Tween(begin: scale, end: scale),
        child: Item(offer: offer),
        builder: (context, value, child) {
            return Transform.scale(
                scale: value,
                child: child,
            );
        },
    );
},

In here, defined a scale property and assigned it to a value of 1.0 if the selectedindex variable we created earlier is equals to the index of the pageview. If not, then it is set to a value of 0.8. So 1.0 for a full scale whiile 0.8 for a lesser scale.

Inside the TAB, we give it a duration of 350ms, set the animation to an ease curve then assigned the scale variable as the values for both the begin and end tween values. Next, assign the item widget to the child property. Remember, this is done to optimize performance since the item widget doesnt use the animation directly. Finally, inside the builder, we return a Transform.scal widget this time around since we want a scale animation. Inside it, we set its scale to the value returned from the TAB. This would trigger the grow and shrink animation between the values 0.8 and 1.0. Then on the next line, we assign the child to the child returned from the TAB and that would be the item widget. Save your work and try it out.

You can see that the items animates accordingly. And one thing to note, the scale up and scale down is controlled by the tween’s begin and end value. So a scale up animated from 0.8 to 1.0 while a scale down does the opposite. Cool. So now, let’s go animate those indicators shall we?

First, let’s go take a look at the indicator widget. It has an isActive boolean which styles the widget differently if isActive is set to true. So it changes its width and color of the Container when the indicator is active.

Okay, let’s go up back to the slider to see how it is used. We use a for loop to add the indicatos as children of a Row widget and all the indicator’s active status is set to false. Let’s change that now. Add the following code:

Row(
...
    children: <Widget>[
    for (int i = 0; i < offers.length; i++)
        if (i == _selectedIndex)
            const Indicator(isActive: true)
        else
            const Indicator(isActive: false),
    ],
),

In here, we added a condition to check if loops index is equal to the selectedIndex from our state and if it is, we display an active indicator else we display an inactive indicator. Save your work and try it out.

We can see that the indicator updates but we dont have any animation. It just snaps to the active indicator design. Why is that so?

Let’s head over to the indicator widget and take a look at it. If you notice, it is a Container and not an AnimatedContainer so you wont have any animation. Let’s change that up right now:

...
return AnimatedContainer(
    duration: const Duration(milliseconds: 350),
...

Save your work. And now, you have a nice looking slider animation.