如何在Flutter中使用go_router关闭Drawer时平滑跳转至新页面
解决GoRouter跳转时Drawer关闭无动画的问题
问题根源在于:你每个页面都单独嵌套了Scaffold+Drawer,点击导航时先关闭Drawer再跳转页面,此时原页面的Scaffold会被直接销毁,Drawer的关闭动画自然被中断。
不用延迟的最优方案是把Scaffold和Drawer抽成全局外层容器,让路由切换的只是Scaffold的body内容,这样Drawer所在的容器不会被销毁,关闭动画能完整播放,同时完成页面切换。
修改后的完整代码如下:
import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; void main() { runApp(const MainApp()); } final _router = GoRouter( routes: <RouteBase>[ ShellRoute( builder: (context, state, child) { // 外层统一渲染带Drawer的Scaffold return Scaffold( drawer: const AppDrawer(), appBar: AppBar(title: Text(state.location == '/' ? 'Home Screen' : 'News Screen')), body: child, // 子路由内容作为Scaffold的body ); }, routes: <RouteBase>[ GoRoute( path: '/', builder: (context, state) => const HomeContent(), ), GoRoute( path: '/news', builder: (context, state) => const NewsContent(), ), ], ), ], ); class MainApp extends StatelessWidget { const MainApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp.router( routerConfig: _router, ); } } // 仅保留页面核心内容,不再嵌套Scaffold class HomeContent extends StatelessWidget { const HomeContent({super.key}); @override Widget build(BuildContext context) { return const Center(child: Text("Home")); } } // 仅保留页面核心内容,不再嵌套Scaffold class NewsContent extends StatelessWidget { const NewsContent({super.key}); @override Widget build(BuildContext context) { return const Center(child: Text("News")); } } class AppDrawer extends StatelessWidget { const AppDrawer({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Drawer( child: SafeArea( child: ListView( children: [ ListTile( title: const Text('Home'), onTap: () { Navigator.pop(context); // 先关闭Drawer,动画正常执行 // 避免重复跳转当前页面 if (GoRouterState.of(context).location != '/') { context.go('/'); // 仅替换Scaffold的body,外层容器不销毁 } }, ), ListTile( title: const Text('News'), onTap: () { Navigator.pop(context); if (GoRouterState.of(context).location != '/news') { context.go('/news'); } }, ), ], ), ), ); } }
关键改动说明:
- 用
ShellRoute作为外层路由,统一管理带Drawer的Scaffold,子路由仅负责渲染页面核心内容。 - 拆分原页面组件,去掉重复的Scaffold嵌套,让路由切换仅作用于Scaffold的body部分。
- Drawer的导航逻辑中,先关闭Drawer(此时外层Scaffold仍存在,动画完整播放),再执行路由跳转,避免页面销毁打断动画。
- 增加当前路由判断,防止重复跳转同一页面。
内容的提问来源于stack exchange,提问作者SP86
相关产品推荐
相关产品推荐

