Drawer Animation in Flutter

Payam Asefi
The Startup
Published in
4 min readNov 2, 2020

I recently watched Marcin Szałeks video about complex UI where he creates some awesome animations using flutter. In this post we are going to create one of those beautiful animations.

First lets take a look at the project structure before adding animations:

home_form.dart

@override
Widget build(BuildContext context) {
return Stack(
children: [
// Works as Drawer
Scaffold(
backgroundColor: const Color(0xff22a6b3),
body:const DrawerData(),
),

// Works as Main Screen
Scaffold(
backgroundColor:Colors.white,
appBar: PreferredSize(
preferredSize: Size.fromHeight(200),
child: Container(
color: const Color(0xffee5253),
child: Padding(
padding: const EdgeInsets.fromLTRB(12, 24, 12, 12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
IconButton(
icon: Icon(Icons.menu),
),
Padding(
padding: const EdgeInsets.only(top: 24,bottom: 12),
child: Text('Welcome',style: Theme.of(context).textTheme.headline4,),
),
const Text('Improve your language skill\nby selecting one of the following languages',
style: TextStyle(
fontSize: 17,
fontStyle: FontStyle.italic
),)
],
),
),
),
),
body: const DummyData(),
) ],
);
}

We have a Stack with two child, the first one works as the drawer and the second one works as the main page. Without the animation and movement we can only see the second child on screen:

And the result we want is something like this:

In order to achieve this goal we should:

  • Make main screen smaller.
  • Move the main screen to the right.
  • Create a smooth transition.

Make main screen smaller

Transform is a widget that applies a transformation before painting its child, you can find more about this widget in here. So lets wrap our main content with a Transform widget:

Stack(
children: [
Scaffold(
backgroundColor: const Color(0xff22a6b3),
body:const DrawerData(),
),
Transform(
transform: Matrix4.identity()
..scale(0.6),
alignment: Alignment.center,
child: Scaffold(),
)
],
);

The transform is the matrix to transform the child during painting and by using scale we made the child 60% of the real size, if you want to find out more about 4D Matrix take a look at this codemagic post. Now our app must look like this:

flutter drawer animation

Move the main screen to the right

Moving the screen is not a hard task, with the help of previously created Tranform widget we move our child widget:

final rightSlide = MediaQuery.of(context).size.width * 0.6;
...
transform: Matrix4.identity()
..translate(rightSlide)
..scale(0.6),

We should consider that changing the order of the transform value may change the result

And the current state of the app:

Create a smooth transition

To make a smooth transition to the right side of the screen we need AnimationController, it’s a class to handle animations like:

To handle duration and vsync we also need to use a Mixin:

class _HomeFormState extends State<HomeForm>
with SingleTickerProviderStateMixin {
AnimationController _animationController;

@override
void initState() {
super.initState();
_animationController =
AnimationController(vsync: this, duration: Duration(milliseconds: 300));
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}

vsync allows us to mute, slow or fast forward our animations.

We also need a method to handle the open/close animation:

_toggleAnimation() {
_animationController.isDismissed
? _animationController.forward()
: _animationController.reverse();
}

Where:

  • Forward: Starts running this animation forwards (towards the end).
  • Reverse: Starts running this animation in reverse (towards the beginning).

Now all we need is wrap our Stack with a AnimatedBuilder and change the scale and translate value with the _animationController related value, so:

return AnimatedBuilder(
animation: _animationController,
builder: (context,child){
// Related Scale and Translate values
double slide = rightSlide*_animationController.value;
double scale = 1-(_animationController.value*0.3);

return Stack(
children: [
Scaffold(
backgroundColor: const Color(0xff22a6b3),
body:const DrawerData(),
),
Transform(
transform: Matrix4.identity()
..translate(slide)
..scale(scale),
alignment: Alignment.center,
child: Scaffold(),
)
],
);
},
);

We also change the drawer menu icon with an AnimatedIcon for a better UI design:

IconButton(
onPressed: ()=>_toggleAnimation(),
icon: AnimatedIcon(
icon: AnimatedIcons.menu_close,
progress: _animationController,
),
)

And that’s all we need for a smooth transition:

You can find the final code on Github!

--

--

Payam Asefi
The Startup

Senior Flutter Developer with a passion for coding, movies, and nature. Let's connect and code together!