1

I am trying to create a Material NavigationRail that, with the click of a button on the rail, shows a drawer with secondary destinations in my app. I have a Scaffold that as a body has a Row containing the NavigationRail and a Stack. The Stack contains the actual content of my homepage as well as the drawer, but only when the button has been clicked (I use riverpod).

I want to animate the drawer in and out on button clicks, but the drawer appears on top of the NavigationRail. How do I keep the rail in front of the drawer? If I include it in the stack, the content and the drawer are shifted to the left, behind the rail, so that does not work.

Currently, the animation looks like this:

enter image description here

I made a Dartpad that reproduces the behaviour: DartPad

Md. Yeasin Sheikh
  • 54,221
  • 7
  • 29
  • 56
Wessel
  • 617
  • 4
  • 13

1 Answers1

0

You can use only Stack with AnimatedPosition widget.

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  bool drawerOpen = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Stack(
      children: [
        AnimatedPositioned(
          duration: const Duration(milliseconds: 200),
          left: drawerOpen ? 64 : -300,
          width: 300,
          top: 0,
          bottom: 0,
          child: const SizedBox(
            height: double.infinity,
            width: 300,
            child: ColoredBox(color: Colors.blue),
          ),
        ),
        Positioned(
          left: 0,
          top: 0,
          bottom: 0,
          width: 64,
          child: NavigationRail(
            backgroundColor: Colors.deepPurple,
            leading: IconButton(
              icon: const Icon(Icons.menu),
              onPressed: () {
                setState(() {
                  drawerOpen = !drawerOpen;
                });
              },
            ),
            destinations: const [
              NavigationRailDestination(
                  icon: Icon(Icons.abc), label: Text("A")),
              NavigationRailDestination(
                  icon: Icon(Icons.ac_unit), label: Text("B"))
            ],
            selectedIndex: 1,
          ),
        ),
      ],
    ));
  }
}
Md. Yeasin Sheikh
  • 54,221
  • 7
  • 29
  • 56
  • That is the intended behaviour, yes! Is this the best way to go about this though? I prefer not to force specific dimension or positions using, e.g., Positioned if there is a nicer alternative. Many thanks at any rate! – Wessel Jan 22 '23 at 22:11
  • If we use row, the last child will paint over the other while Transform is just about manipulating on UI, not actual shape(sizing you can say). I've thought using SizeTransition on this case. But while you already have Stack widget, I used this way. well there are N ways to do a thing which will cause no issue. – Md. Yeasin Sheikh Jan 22 '23 at 22:15