Drawer Animation in Flutter

Payam Asefi
Nov 2 · 4 min read
Image for post
Image for post

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:

Image for post
Image for post

And the result we want is something like this:

Image for post
Image for post

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:

Image for post
Image for post
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:

Image for post
Image for post

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:

Image for post
Image for post

You can find the final code on Github!

The Startup

Medium's largest active publication, followed by +734K people. Follow to join our community.

Payam Asefi

Written by

Flutter developer and a nature lover. Besides coding I like playing video games, twitting, watching movies and wasting my time on Youtube!

The Startup

Medium's largest active publication, followed by +734K people. Follow to join our community.

Payam Asefi

Written by

Flutter developer and a nature lover. Besides coding I like playing video games, twitting, watching movies and wasting my time on Youtube!

The Startup

Medium's largest active publication, followed by +734K people. Follow to join our community.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store