Button Animations In Flutter using AnimatedBuilder

In this post we will learn to build button animations in Flutter using AnimatedBuilder widget. We will learn to create different variations of sweep effects like left to right and right to left on button click.

Introduction

Showing animations in any app is a great way to improve user experience. Even a small and basic animation can sometimes wow a user. So in this post, we will learn to add some cool button animations that will help to impress your users 😉

By the end of this tutorial, we will have achieved the following button animations:

DecisionMentor app
  • Left to right sweep
  • Right to left sweep
  • Bottom to top sweep
  • Top to bottom sweep
Button Sweep Animations In Flutter
Button Sweep Animations In Flutter

Setup Left To Sweep Button Animation In Flutter

Let’s start by creating the first sweep animation i.e. left to right sweep animation.

Define the different sweep types.

enum Sweep { left, right, top, bottom }

Create a class for SweepAnimatedButton widget.

import 'package:flutter/material.dart';

class SweepAnimmatedButton extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _AnimatedButtonState();
}

class _AnimatedButtonState extends State<SweepAnimmatedButton>
    with TickerProviderStateMixin {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return null;
  }
}

Here we have started a regular Stateful widget but with TickerProviderStateMixin which is needed for creating our animations.

Next, we start by creating a GestureDetector that wraps a Container and a Text widget inside a Stack making it appear as a button.

class _AnimatedButtonState extends State<SweepAnimmatedButton>
    with TickerProviderStateMixin {
  double _btnWidth = 140.0;
  double _btnHeight = 40.0;
  
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
        onTap: () {},
        child: Stack(
          overflow: Overflow.clip,
          children: <Widget>[
            Container(
              width: _btnWidth,
              height: _btnHeight,
              color: Colors.blue,
            ),
            Positioned(
              child: Container(
                width: _btnWidth,
                height: _btnHeight,
                child: Center(
                  child: Text(
                    "Sweep demo",
                    style: TextStyle(color: Colors.white, fontSize: 16.0),
                  ),
                ),
              ),
            )
          ],
        ));
  }
}
Gesture Detector Button
Gesture Detector Button

We currently have a button with single color but in final our animation we want to show a transition of two colors. To get the feel of our end result, we will add another item inside the stack.

Stack(
          overflow: Overflow.clip,
          children: <Widget>[
            Container(
              width: _btnWidth,
              height: _btnHeight,
              color: Colors.blue,
            ),
            Positioned(
              left: _btnWidth/2,
              child: Container(
                width: _btnWidth,
                height: _btnHeight,
                color: Colors.green,
              ),
            ),
            Positioned(
              child: Container(
...

We added a Positioned container as the second element of the Stack widget. If you run the code right now, you would see that our button appears half blue and half green in color. This is because we have positioned the green container’s left value as half of the total available width.

Now that we have a feel for the animation, let’s add an AnimationController.

AnimationController _animationController;

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
        vsync: this,
        duration: Duration(milliseconds: 400),
        lowerBound: 0,
        upperBound: _btnWidth);
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }

We have defined _animationController in the initState of our widget. The duration property is set to 400 milliseconds which is the duration of the sweep animation.

Every animation controller will have a value at any given point of animation. The lowerBound and upperBound properties denote the minimum and maximum values. We have set the upperBound to match with the width of the button.

Now we use the AnimatedBuilder class create the sweep animation.

GestureDetector(
        onTap: () {},
        child: AnimatedBuilder(
          animation: _animationController,
          builder: (context, Widget child) {
            return Stack(

First wrap the Stack widget by the AnimatedBuilder. The animation is set as our defined _animationController.

Next, trigger the animation on the onTap event.

GestureDetector(
        onTap: () {
          _animationController.forward();
        },

The forward call starts the animation from it’s lower value to the upper value.

Finally, we need to adjust the position of the green container based on the value provided by the _animationController.

Positioned(
  left: _animationController.value,
  child: Container(
	width: _btnWidth,
	height: _btnHeight,
	color: Colors.green,
  ),
),

Since we have wrapped everything inside the AnimatedBuilder class, as the upper value of the animation changes, the widget gets rebuilt creating the animation effect of color change.

Left To Right Sweep Animation
Left To Right Sweep Animation

Wrapping Up

In this post we saw how easy it was to create a cool button sweep animation in Flutter using the AnimatedController widget. Although we learnt to build only the left to right sweep in this post, you can easily replicate the same effect for right to left and top/bottom sweeps as well. All you need is to play around with the left/top/right/bottom properties of the Positioned widget.

Good luck~

Related Articles