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:
- Left to right sweep
- Right to left sweep
- Bottom to top sweep
- Top to bottom sweep

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),
),
),
),
)
],
));
}
}

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.

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
You must be logged in to post a comment.