Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Navigation with a drawer does not have closing animation #26954

Open
The-Redhat opened this issue Jan 23, 2019 · 35 comments
Open

Navigation with a drawer does not have closing animation #26954

The-Redhat opened this issue Jan 23, 2019 · 35 comments
Labels
a: quality A truly polished experience c: new feature Nothing broken; request for a new capability f: material design flutter/packages/flutter/material repository. found in release: 3.3 Found to occur in 3.3 found in release: 3.7 Found to occur in 3.7 framework flutter/packages/flutter repository. See also f: labels. has reproducible steps The issue has been confirmed reproducible and is ready to work on P2 Important issues not at the top of the work list team-design Owned by Design Languages team triaged-design Triaged by Design Languages team

Comments

@The-Redhat
Copy link
Contributor

Hey,
I'm currently developing a flutter app. Because of its flexibility I use a navigation drawer. I came across multiple tutorials about navigation with a drawer in flutter, but no one was really satisfying. The first approach is to use one Scaffold with multiple layouts inside, like described here. But like one of the comments says it isn't a clean solution especially in a big app. Another approach is described here. It uses multiple Scaffolds and pushes them with Navigator.of(context).push(...). Because of this method you have an animation between pages and are able to use the back button on android. So my question is, if there is a proper solution to use a navigation drawer. Maybe I'm just missing something and there's an example.

Thanks in advance!

@Kartik1607
Copy link
Contributor

Because of this method you have an animation between pages and are able to use the back button on android.

So you want that when you click a link on drawer, just the main screen should be changed with no animation, and clicking back button should exit the app instead of going back to previous screen?

@The-Redhat
Copy link
Contributor Author

The-Redhat commented Jan 23, 2019

yes like in for example in the Gmail App. But for me the back button is not really the problem. It's more the animation. And you don't really find any documentation about navigation with a drawer.

@Kartik1607
Copy link
Contributor

To remove animation you can use PageRouteBuilder
Sample Code

          Navigator.push(context, PageRouteBuilder(
              opaque: false,
              pageBuilder: (context, _, __) {
                return SecondScreen();
              },
              transitionsBuilder: (_, __, ___, Widget child) {
                return child;
              }
            ));

@The-Redhat
Copy link
Contributor Author

The-Redhat commented Jan 23, 2019

I tested it and for me it doesn't really looked nice. And in my eyes there must be a better solution.

@zoechi
Copy link
Contributor

zoechi commented Jan 23, 2019

doesn't really looked nice

How does it not look nice?
What should be different for it to look nice?

Perhaps you just want a https://docs.flutter.io/flutter/widgets/PageView-class.html instead of the Navigator.

@The-Redhat
Copy link
Contributor Author

@zoechi
screencast

Maybe I am doing something wrong, but i created a test project and used what @Kartik1607 suggested.

@The-Redhat
Copy link
Contributor Author

code:

class StartPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('AppBar'),
      ),
      drawer: TestDrawer(),
      body: Center(
        child: Text('drawer page'),
      ),
    );
  }
}

class FirstPage extends StatelessWidget {
  final String text;

  const FirstPage({Key key, this.text}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Text(text),
      appBar: AppBar(
        title: Text(text),
      ),
      drawer: TestDrawer(),
    );
  }
}

class TestDrawer extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Drawer(
      child: ListView(
        children: <Widget>[
          ListTile(
            title: Text('Item 1'),
            onTap: () {
              Navigator.of(context).pop();
              Navigator.of(context).push(
                PageRouteBuilder(pageBuilder: (context, _, __) {
                  return FirstPage(
                    text: 'Item 1',
                  );
                }, transitionsBuilder: (_, __, ___, Widget child) {
                  return child;
                }),
              );

            },
          ),
          ListTile(
            title: Text('Item 2'),
            onTap: () {
              Navigator.of(context).pop();
              Navigator.of(context).push(
                PageRouteBuilder(
                  pageBuilder: (context, _, __) {
                    return FirstPage(text: 'Item 2');
                  },
                ),
              );
            },
          )
        ],
      ),
    );
  }
}

@zoechi
Copy link
Contributor

zoechi commented Jan 23, 2019

What would need to be different for it to look nice?
Perhaps https://stackoverflow.com/questions/51548451/flutter-drawer-below-appbar ?

@The-Redhat
Copy link
Contributor Author

When you compare to the Gmail app you can clearly see that there's no real closing animation of the drawer.

@zoechi zoechi added waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds framework flutter/packages/flutter repository. See also f: labels. labels Jan 23, 2019
@Kartik1607
Copy link
Contributor

What you need is something like Nested/Child routes. This answer is what would help you.

@The-Redhat
Copy link
Contributor Author

Thanks @Kartik1607 that's a good idea. I will take a look at it. But I wonder why there isn't a solution for my Problem, it's not that specific.

@no-response no-response bot removed the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Jan 23, 2019
@chankruze
Copy link

The default drawer has the same animation like gmail. I didn't see any difference.

@The-Redhat
Copy link
Contributor Author

But my previous video looks different than gmail ?

@The-Redhat
Copy link
Contributor Author

@Kartik1607 I tried it with your solution, but there isn't a close animation like before.

@The-Redhat
Copy link
Contributor Author

Do you know an open source example app that uses a drawer and a Scaffold for each Page ?

@kyleorin
Copy link

Do you know an open source example app that uses a drawer and a Scaffold for each Page ?

Check the gallery app. Which version of flutter are you using? Maybe consider switching from pageroutebuilder?

@Kartik1607
Copy link
Contributor

Kartik1607 commented Jan 24, 2019

I was thinking that since flutter is mostly favored towards composition (Padding, Center etc) instead of properties, if we are somehow able to implement routing same way taking inspiration from React-Router and Angular Router, this could lead to very easy transition and ease of use.

eg

Router(
    Route(path:'/', widget:RootWidget()),
    Route(path:'/details', widget:DetailsWidget()),
    ...
)

This could solve problems of child router. But, I see some shortcomings, namely Widgets like Hero which depend on Navigator . I think fluro was able to solve this issue, but fluro also taps into routes of MaterialApp and CupertinoApp. Also, how would one be able to use Hero transitions in child router? How should one be able to trigger changes in parent router instead of child router?

Nevertheless, it would be nice to have router as a widget instead of a property. For the time being, I think there is a lack of resources for architecture of flutter app navigation. I'll try to take out some time and create some applications and write up an article.

@The-Redhat
Copy link
Contributor Author

When using navigation drawer I came accros another problem. You cannot change the AppBar from a drawer page in an elegant way. On android you have getActionBar and in my opinion such a feature is missing in flutter. It would be nice if there's a possibility to call AppBar.of(context) to change the title and the actions of the AppBar.

@zoechi
Copy link
Contributor

zoechi commented Feb 19, 2019

@The-Redhat

On android you have getActionBar and

I'd suggest to ask on StackOverflow how to do this in Flutter.

@The-Redhat
Copy link
Contributor Author

The-Redhat commented Feb 19, 2019

That's not my problem. I think that flutter should provide either a guide or a component. @Kartik1607 could include something like that.

@kelvin1hui
Copy link

I have the same problem with the drawer navigation.
I am not satisfy with the new page I call from the drawer stack over the original screen and the new screen have a new drawer.

What I expected: After clicking on the new page button from the drawer, the drawer close with animation while the new page replace the original page in the background. The drawer should be on top of everything and shared by every page in the same route level.

I am a bit disappointed with this while React Native can do this a lot better. Flutter should have something like Drawer Navigation, Stack Navigation and Tab Navigation.
For example : https://reactnavigation.org/docs/en/drawer-based-navigation.html
Expected animation of drawer navigation: https://youtu.be/KGoE6IPhdwQ?t=683

@kelvin1hui
Copy link

I am currently using this workaround.
https://medium.com/@kashifmin/flutter-setting-up-a-navigation-drawer-with-multiple-fragments-widgets-1914fda3c8a8

However, it is so complicated to change the app bar inside the "fragment".

@coyksdev
Copy link

coyksdev commented Jun 6, 2019

@kelvin1hui Did you figured out the way to change the scaffold content?

@fresswolf
Copy link

fresswolf commented Aug 19, 2019

@kelvin1hui @campanagerald you don't have to reuse the same Scaffold over your screens.
Just create one Scaffold per screen and give them all the same key
Scaffold(key: ValueKey("drawerScaffold"),body: Text("first screen"))
Scaffold(key: ValueKey("drawerScaffold"),body: Text("second screen"))
That way the drawer animation is smooth

@juliocbcotta
Copy link

Today I faced this problem too. Selecting an item in the drawer and updating the content while keeping the drawer in place. I found no good solution. Using Navigator.push seemed wrong too, the animations of a new AppBar sliding up (when using MaterialRouter) or from right-left (when using CupertinoRouter) weren't pleasant as I could see the previous page while the enter animation was playing.
So I did this when an item in the Drawer is tapped.

             onTap: () async {
                    // closes drawer.
                    Navigator.of(context).pop();
                    if (item.id != selectedItemId) {
                      await Future.delayed(Duration(milliseconds: 250), () {
                        onItemSelected(item.id);
                      });
                    }
                  },

Instead of pushing a new page I close the Drawer and then wait for the animation to finish (250 is a magic number that seemed about right) then I change what my build method returns using setState. And all pages that are open from the drawer sets a new scaffold and new drawer, and all of that pages lifts the onItemSelected callback to the root page. This allows me to change what is shown in the AppBar for each page without having to push a new page in the stack.

It would be great if Navigator.of(context).pop(); returned a future, that would complete when the current page pop animation finishes.

@devnoname120
Copy link

Did you try the solution above your message?

@juliocbcotta
Copy link

Did you try the solution above your message?

I just did. I could use that approach, but I would have to disable the animations using PageRouteBuilder and the delay I proposed above.

@The-Redhat
Copy link
Contributor Author

The-Redhat commented Sep 14, 2019

For me the suggested solution above didn't worked. Instead of a ValueKey I now use the same GlobalKey for every Scaffold. To avoid duplicate GlobalKeys in the widget tree I set the transitionDuration of the PageRouteBuilder to zero.

Although I have a solution to my problem, I will leave this issue open. There should be more documentation, something like 'navigating with drawer and routes'.

@matheus-rdo
Copy link

This redraw animation seems strange to me too. I believe Flutter can incorporate something based on Android Fragments.

@TahaTesser TahaTesser added f: material design flutter/packages/flutter/material repository. f: routes Navigator, Router, and related APIs. a: quality A truly polished experience labels Feb 28, 2020
@TahaTesser
Copy link
Member

TahaTesser commented May 29, 2020

Code Sample
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material App',
      theme: ThemeData.dark(),
      home: StartPage(),
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Material App Bar'),
      ),
      body: Center(
        child: Container(
          child: Text('Hello World'),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {},
      ),
    );
  }
}

class StartPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('AppBar'),
      ),
      drawer: TestDrawer(),
      body: Center(
        child: Text('drawer page'),
      ),
    );
  }
}

class FirstPage extends StatelessWidget {
  final String text;

  const FirstPage({Key key, this.text}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Text(text),
      appBar: AppBar(
        title: Text(text),
      ),
      drawer: TestDrawer(),
    );
  }
}

class TestDrawer extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Drawer(
      child: ListView(
        children: <Widget>[
          ListTile(
            title: Text('Item 1'),
            onTap: () {
              Navigator.of(context).pop();
              Navigator.of(context).push(
                PageRouteBuilder(pageBuilder: (context, _, __) {
                  return FirstPage(
                    text: 'Item 1',
                  );
                }, transitionsBuilder: (_, __, ___, Widget child) {
                  return child;
                }),
              );
            },
          ),
          ListTile(
            title: Text('Item 2'),
            onTap: () {
              Navigator.of(context).pop();
              Navigator.of(context).push(
                PageRouteBuilder(
                  pageBuilder: (context, _, __) {
                    return FirstPage(text: 'Item 2');
                  },
                ),
              );
            },
          )
        ],
      ),
    );
  }
}

flutter doctor -v
[✓] Flutter (Channel dev, 1.19.0-1.0.pre, on Mac OS X 10.15.5 19F96, locale
    en-GB)
    • Flutter version 1.19.0-1.0.pre at /Users/tahatesser/Code/flutter_dev
    • Framework revision 456d80b9dd (3 weeks ago), 2020-05-11 11:45:03 -0400
    • Engine revision d96f962ca2
    • Dart version 2.9.0 (build 2.9.0-7.0.dev 092ed38a87)

 
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
    • Android SDK at /Users/tahatesser/Code/sdk
    • Platform android-29, build-tools 29.0.3
    • ANDROID_HOME = /Users/tahatesser/Code/sdk
    • Java binary at: /Applications/Android
      Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build
      1.8.0_242-release-1644-b3-6222593)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 11.5)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 11.5, Build version 11E608c
    • CocoaPods version 1.9.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.0)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 45.1.2
    • Dart plugin version 193.7361
    • Java version OpenJDK Runtime Environment (build
      1.8.0_242-release-1644-b3-6222593)

[✓] VS Code (version 1.45.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.10.2

[✓] Connected device (5 available)
    • SM M305F   • 32003c30dc19668f                     • android-arm64  •
      Android 10 (API 29)
    • iPhone 11  • 0EC80516-8F99-4A0C-89ED-2273579862F9 • ios            •
      com.apple.CoreSimulator.SimRuntime.iOS-13-5 (simulator)
    • macOS      • macOS                                • darwin-x64     • Mac
      OS X 10.15.5 19F96
    • Web Server • web-server                           • web-javascript •
      Flutter Tools
    • Chrome     • chrome                               • web-javascript •
      Google Chrome 83.0.4103.61

• No issues found!

@TahaTesser TahaTesser added found in release: 1.19 Found to occur in 1.19 has reproducible steps The issue has been confirmed reproducible and is ready to work on labels May 29, 2020
@TahaTesser
Copy link
Member

Based on comments and my testing, this can be improved.

code sample
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material App',
      theme: ThemeData.dark(),
      home: StartPage(),
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Material App Bar'),
      ),
      body: Center(
        child: Container(
          child: Text('Hello World'),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {},
      ),
    );
  }
}

class StartPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('AppBar'),
      ),
      drawer: TestDrawer(),
      body: Center(
        child: Text('drawer page'),
      ),
    );
  }
}

class FirstPage extends StatelessWidget {
  final String text;

  const FirstPage({Key key, this.text}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Text(text),
      appBar: AppBar(
        title: Text(text),
      ),
      drawer: TestDrawer(),
    );
  }
}

class TestDrawer extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Drawer(
      child: ListView(
        children: <Widget>[
          ListTile(
            title: Text('Item 1'),
            onTap: () {
              Navigator.of(context).pop();
              Navigator.of(context).push(
                PageRouteBuilder(pageBuilder: (context, _, __) {
                  return FirstPage(
                    text: 'Item 1',
                  );
                }, transitionsBuilder: (_, __, ___, Widget child) {
                  return child;
                }),
              );
            },
          ),
          ListTile(
            title: Text('Item 2'),
            onTap: () {
              Navigator.of(context).pop();
              Navigator.of(context).push(
                PageRouteBuilder(
                  pageBuilder: (context, _, __) {
                    return FirstPage(text: 'Item 2');
                  },
                ),
              );
            },
          )
        ],
      ),
    );
  }
}
flutter doctor -v
[✓] Flutter (Channel stable, 1.22.5, on macOS 11.1 20C69 darwin-x64, locale en-GB)
    • Flutter version 1.22.5 at /Users/tahatesser/Code/flutter_stable
    • Framework revision 7891006299 (6 weeks ago), 2020-12-10 11:54:40 -0800
    • Engine revision ae90085a84
    • Dart version 2.10.4

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    • Android SDK at /Volumes/Extreme/SDK
    • Platform android-30, build-tools 30.0.3
    • ANDROID_HOME = /Volumes/Extreme/SDK
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 12.3)
    • Xcode at /Volumes/Extreme/Xcode.app/Contents/Developer
    • Xcode 12.3, Build version 12C33
    • CocoaPods version 1.10.1

[!] Android Studio (version 4.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)

[✓] VS Code (version 1.52.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.18.1

[✓] Connected device (1 available)
    • Android SDK built for x86 (mobile) • emulator-5554 • android-x86 • Android 10 (API 29) (emulator)

! Doctor found issues in 1 category.
[✓] Flutter (Channel master, 1.26.0-2.0.pre.402, on macOS 11.1 20C69 darwin-x64, locale en-GB)
    • Flutter version 1.26.0-2.0.pre.402 at /Users/tahatesser/Code/flutter_master
    • Framework revision 2a188eeca3 (10 hours ago), 2021-01-17 19:27:00 -0800
    • Engine revision 609036f2bf
    • Dart version 2.12.0 (build 2.12.0-236.0.dev)

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    • Android SDK at /Volumes/Extreme/SDK
    • Platform android-30, build-tools 30.0.3
    • ANDROID_HOME = /Volumes/Extreme/SDK
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS
    • Xcode at /Volumes/Extreme/Xcode.app/Contents/Developer
    • Xcode 12.3, Build version 12C33
    • CocoaPods version 1.10.1

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)

[✓] VS Code (version 1.52.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.18.1

[✓] Connected device (3 available)
    • Android SDK built for x86 (mobile) • emulator-5554 • android-x86    • Android 10 (API 29) (emulator)
    • macOS (desktop)                    • macos         • darwin-x64     • macOS 11.1 20C69 darwin-x64
    • Chrome (web)                       • chrome        • web-javascript • Google Chrome 87.0.4280.141

• No issues found!

@TahaTesser TahaTesser added found in release: 1.22 Found to occur in 1.22 found in release: 1.26 Found to occur in 1.26 and removed found in release: 1.19 Found to occur in 1.19 labels Jan 18, 2021
@maheshj01
Copy link
Member

maheshj01 commented Dec 8, 2022

I Verified the issue on the latest master channel, Navigation Drawer abruptly closes (Without slide transition) when navigating without any transition (Notice item 2).

Android IOS
Screen.Recording.2022-12-08.at.12.35.43.PM.mov
Screen.Recording.2022-12-08.at.12.26.44.PM.mov

But with the default MaterialPageRoute the drawer does close smoothly with slide transition. I will leave this for the team to decide.

code sample
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material App',
      theme: ThemeData.dark(),
      home: StartPage(),
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Material App Bar'),
      ),
      body: Center(
        child: Container(
          child: Text('Hello World'),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {},
      ),
    );
  }
}

class StartPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('AppBar'),
      ),
      drawer: TestDrawer(),
      body: Center(
        child: Text('drawer page'),
      ),
    );
  }
}

class FirstPage extends StatelessWidget {
  final String text;

  const FirstPage({Key? key,required this.text}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly ,
          children: [
            Text(text),
            ElevatedButton(onPressed: () {
              Navigator.of(context).pop();
            }, child: Text('pop'))
          ],
        ),
      ),
      appBar: AppBar(
        title: Text(text),
      ),
      drawer: TestDrawer(),
    );
  }
}

class TestDrawer extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Drawer(
      child: ListView(
        children: <Widget>[
          ListTile(
            title: Text('Item 1'),
            onTap: () {
              Navigator.of(context).pop();
              Navigator.of(context).push(
                MaterialPageRoute(builder: (context)=> FirstPage(text: "Item 1",)  )
              );
            },
          ),
          ListTile(
            title: Text('Item 2'),
            onTap: () {
              Navigator.of(context).pop();
              Navigator.of(context).push(
                PageRouteBuilder(
                  pageBuilder: (context, _, __) {
                    return FirstPage(text: 'Item 2');
                  },
                ),
              );
            },
          ),
          ListTile(
            title: const Text('Fade Transition'),
            onTap: () {
              Navigator.of(context).pop();
              Navigator.of(context).push(
              PageRouteBuilder(
                transitionsBuilder: (context, animation, secondaryAnimation, child) {
                  return FadeTransition(
                    opacity: animation, 
                    child: child,
                  );
                },
                  pageBuilder: (context, _, __) {
                    return FirstPage(text: 'Item 3');
                  })
              );
            },
          ),
          ListTile(
            title: Text('Slide Transition'),
            onTap: () {
              Navigator.of(context).pop();
              Navigator.of(context).push(
              PageRouteBuilder(
                transitionsBuilder: (context, animation, secondaryAnimation, child) {
                  return SlideTransition(
                    position: Tween<Offset>(
                      begin: const Offset(1.0, 0),
                      end: Offset.zero,
                    ).animate(animation),
                    // secondaryAnimation: secondaryAnimation,
                    child: child,
                  );
                },
                  pageBuilder: (context, _, __) {
                    return const FirstPage(text: 'Item 4');
                  })
              );
            },
          ),
        ],
      ),
    );
  }
}
author's code sample
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material App',
      theme: ThemeData.dark(),
      home: StartPage(),
    );
  }
}
class StartPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('AppBar'),
      ),
      drawer: TestDrawer(),
      body: Center(
        child: Text('drawer page'),
      ),
    );
  }
}

class FirstPage extends StatelessWidget {
  final String text;

  const FirstPage({Key? key,required  this.text}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Text(text),
      appBar: AppBar(
        title: Text(text),
      ),
      drawer: TestDrawer(),
    );
  }
}

class TestDrawer extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Drawer(
      child: ListView(
        children: <Widget>[
          ListTile(
            title: Text('Item 1'),
            onTap: () {
              Navigator.of(context).pop();
              Navigator.of(context).push(
                PageRouteBuilder(pageBuilder: (context, _, __) {
                  return FirstPage(
                    text: 'Item 1',
                  );
                }, transitionsBuilder: (_, __, ___, Widget child) {
                  return child;
                }),
              );

            },
          ),
          ListTile(
            title: Text('Item 2'),
            onTap: () {
              Navigator.of(context).pop();
              Navigator.of(context).push(
                PageRouteBuilder(
                  pageBuilder: (context, _, __) {
                    return FirstPage(text: 'Item 2');
                  },
                ),
              );
            },
          )
        ],
      ),
    );
  }
}
flutter doctor -v (mac)
[✓] Flutter (Channel master, 3.7.0-3.0.pre.33, on macOS 12.6 21G115 darwin-arm64, locale en-IN)
    • Flutter version 3.7.0-3.0.pre.33 on channel master 
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 5201856805 (38 minutes ago), 2022-12-05 18:27:21 -0800
    • Engine revision a309d239c4
    • Dart version 2.19.0 (build 2.19.0-463.0.dev)
    • DevTools version 2.20.0
    • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly
      to perform update checks and upgrades.

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0-rc4)
    • Android SDK at /Users/mahesh/Library/Android/sdk
    • Platform android-33, build-tools 33.0.0-rc4
    • ANDROID_HOME = /Users/mahesh/Library/Android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.0.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14A400
    • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2021.2)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)

[✓] IntelliJ IDEA Community Edition (version 2021.2.1)
    • IntelliJ at /Applications/IntelliJ IDEA CE.app
    • Flutter plugin version 61.2.4
    • Dart plugin version 212.5080.8

[✓] VS Code (version 1.70.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.55.20221129

[✓] Connected device (3 available)
    • iPhone 12 Pro (mobile) • 026D5789-9E78-4AD5-B1B2-3F8D4E7F65E4 • ios            •
      com.apple.CoreSimulator.SimRuntime.iOS-14-5 (simulator)
    • macOS (desktop)        • macos                                • darwin-arm64   • macOS 12.6 21G115 darwin-arm64
    • Chrome (web)           • chrome                               • web-javascript • Google Chrome 108.0.5359.94

[✓] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!
[✓] Flutter (Channel stable, 3.3.9, on macOS 12.6 21G115 darwin-arm, locale en-IN)
    • Flutter version 3.3.9 on channel stable at /Users/mahesh/Development/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision b8f7f1f986 (24 hours ago), 2022-11-23 06:43:51 +0900
    • Engine revision 8f2221fbef
    • Dart version 2.18.5
    • DevTools version 2.15.0

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0-rc4)
    • Android SDK at /Users/mahesh/Library/Android/sdk
    • Platform android-33, build-tools 33.0.0-rc4
    • ANDROID_HOME = /Users/mahesh/Library/Android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.0.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14A400
    • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2021.2)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)

[✓] IntelliJ IDEA Community Edition (version 2021.2.1)
    • IntelliJ at /Applications/IntelliJ IDEA CE.app
    • Flutter plugin version 61.2.4
    • Dart plugin version 212.5080.8

[✓] VS Code (version 1.70.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.53.20221101

[✓] Connected device (3 available)
    • iPhone 12 Pro (mobile) • 026D5789-9E78-4AD5-B1B2-3F8D4E7F65E4 • ios            •
      com.apple.CoreSimulator.SimRuntime.iOS-14-5 (simulator)
    • macOS (desktop)        • macos                                • darwin-arm64   • macOS 12.6 21G115 darwin-arm
    • Chrome (web)           • chrome                               • web-javascript • Google Chrome 107.0.5304.110

[✓] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!

@maheshj01 maheshj01 added found in release: 3.3 Found to occur in 3.3 found in release: 3.7 Found to occur in 3.7 and removed found in release: 1.22 Found to occur in 1.22 found in release: 1.26 Found to occur in 1.26 labels Dec 8, 2022
@maheshj01 maheshj01 changed the title Navigation with a drawer Navigation with a drawer does not have closing animation Dec 8, 2022
@flutter-triage-bot flutter-triage-bot bot added multiteam-retriage-candidate team-design Owned by Design Languages team triaged-design Triaged by Design Languages team labels Jul 8, 2023
@tpkowastaken
Copy link

@The-Redhat
I found a workaround that works for now. Looks like so:

android-example.mp4

I made It very similar to gmail (maybe even better for somebody) with just doing a delay in the button in the drawer. I'm using Navigator 2.0 (setHomeWidget function just calls setState on a parent widget updating the scaffold in navigator) and then calling Navigator.pop(context) inside the drawer which closes the drawer and after 200ms replaces the scaffold with a different one. Gmail has the delay longer but you can tinker with it and see what works for you. Here is a code sample:

//call this from a button in a drawer
onTap: () async {
  if (page == NavigationDrawerItem.automatickeObjednavky) {//if the user clicks the selected page
    Navigator.pop(context);
  } else {
    Navigator.pop(context);//close the drawer
    await Future.delayed(const Duration(milliseconds: 200));//wait for the drawer to close (or at least trigger the animation)
    setHomeWidget(AutoPage(//switch to the different page
      setHomeWidget: setHomeWidget,
    ));
  }
},

Navigator 2.0 Implementation

class _MyAppState extends State<MyApp> {
  void setHomeWidget(Widget widget) {
    setState(() {
      homeWidget = widget;
    });
  }

  late Widget homeWidget;
  @override
  void initState() {
    homeWidget = LoggingInWidget(setHomeWidget: setHomeWidget);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        home: Navigator(
          pages: [
            MaterialPage(child: homeWidget),
          ],
          onPopPage: (route, result) {
            return route.didPop(result);
          },
        ));
  }
}

In case you would need any details You can take a look at the whole app which I'm writing. It's opensource: https://github.com/tpkowastaken/autojidelna/tree/35987cdcbe1fd699664643a283456abd52d7b9bc

You also said that the appbar is not easily set - You can just put the appbar widget into a stateful widget make it a variable and call setState on that variable. Other option is to use ValueListenableBuilder Which would only reload the specific thing and not the whole widget. Both are used in my app so you can also take a look there. Hope It helps!

@flutter-triage-bot flutter-triage-bot bot removed the triaged-design Triaged by Design Languages team label Oct 15, 2023
@flutter-triage-bot
Copy link

This issue is missing a priority label. Please set a priority label when adding the triaged-design label.

@HansMuller
Copy link
Contributor

HansMuller commented Oct 18, 2023

Making it possible to specify the NavigationDrawer's open and close animation durations and curves sounds like a resonable proposal. If someone wants to contribute a PR it would be worth considering how to compactly specify both the curve and reverse curve for both open and close, as well as the durations for both transitions.

@HansMuller HansMuller added P2 Important issues not at the top of the work list triaged-design Triaged by Design Languages team c: new feature Nothing broken; request for a new capability and removed f: routes Navigator, Router, and related APIs. labels Oct 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a: quality A truly polished experience c: new feature Nothing broken; request for a new capability f: material design flutter/packages/flutter/material repository. found in release: 3.3 Found to occur in 3.3 found in release: 3.7 Found to occur in 3.7 framework flutter/packages/flutter repository. See also f: labels. has reproducible steps The issue has been confirmed reproducible and is ready to work on P2 Important issues not at the top of the work list team-design Owned by Design Languages team triaged-design Triaged by Design Languages team
Projects
None yet
Development

No branches or pull requests