Create an Animated Stack Menu in Flutter
Animation in Flutter is really cool. There are multiple ways to do it. In this post, we are going to create an Animated stack drawer navigation. When the hamburger menu button is pressed, the main screen slide right to show the drawer.
For our menu, we’re going to use a simple Stack with items that we can position however we want. We’ll be using the animation controller to drive all the animations in our menu.

import 'package:flutter/material.dart'; class StackPage extends StatefulWidget { @override _StackPageState createState() => _StackPageState(); } class _StackPageState extends State<StackPage> with SingleTickerProviderStateMixin { AnimationController _controller; @override void initState() { _controller = AnimationController(vsync: this, duration: Duration(milliseconds: 500)); super.initState(); } void _toggle() { setState(() { _controller.isDismissed ? _controller.forward() : _controller.reverse(); }); } FlatButton _menuItem(IconData icon, String text, VoidCallback onPressed){ return FlatButton(onPressed: onPressed, child: Row( children: [ Icon(icon, color: Colors.white,), SizedBox(width: 8,), Text(text, style: TextStyle(color: Colors.white),) ], )); } @override Widget build(BuildContext context) { return AnimatedBuilder( animation: _controller, builder: (BuildContext context, Widget child) { double slide = 50 * _controller.value; double scale = 1 - (_controller.value * 0.5); return Stack( children: [ Container( width: double.infinity, color: Colors.lightBlueAccent, child: Padding( padding: const EdgeInsets.only( top: 50.0, left: 16.0, right: 16.0, bottom: 16.0), child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Navigation', style: Theme.of(context).textTheme.headline6, ), _menuItem(Icons.home, 'Home', (){}), _menuItem(Icons.pages, 'Page 1', (){}), _menuItem(Icons.palette, 'Page 2', (){}), _menuItem(Icons.close, 'Close Menu', () => _toggle()), ], ), flex: 5, ), Expanded( child: Container(), flex: 5, ) ], ), ), ), Transform( transform: Matrix4.identity() ..translate(slide) ..scale(scale), alignment: Alignment.centerRight, child: Scaffold( appBar: AppBar( title: Text('Example'), actions: [ IconButton( icon: Icon(Icons.dehaze), onPressed: () { _toggle(); }, ) ], ), body: Center( child: Text('Main page'), ), ), ), ], ); }, ); } @override void dispose() { _controller.dispose(); super.dispose(); } }