使用animations库的OpenContainer时如何修改go_router的location?
解决OpenContainer跳转时更新GoRouter router.location的方案
方案一:将OpenContainer过渡集成到GoRouter页面转场(推荐)
让GoRouter完全管理路由,自动同步router.location,同时保留OpenContainer的过渡效果。
- 配置GoRouter路由,添加自定义过渡
修改GoRouter配置,为目标路由设置pageBuilder,使用和OpenContainer对应的过渡动画:
final GoRouter router = GoRouter( routes: [ GoRoute( path: '/', builder: (context, state) => const HomePage(), routes: [ GoRoute( path: 'categories', name: 'categories', pageBuilder: (context, state) { return CustomTransitionPage( key: state.pageKey, child: const CategoryPage(), // 对应ContainerTransitionType.fade过渡 transitionsBuilder: (context, animation, secondaryAnimation, child) { return FadeTransition( opacity: CurvedAnimation( parent: animation, curve: Curves.easeInOut, ), child: child, ); }, transitionDuration: const Duration(milliseconds: 300), // 和OpenContainer默认时长一致 ); }, ), ], ), ], );
- 修改OpenContainerWrapper调用逻辑
不再依赖OpenContainer的路由跳转,直接用GoRouter导航,同时保留OpenContainer的closed状态交互:
// 调用处代码修改 return GestureDetector( onTap: () { // GoRouter跳转自动更新location GoRouter.of(context).pushNamed('categories'); }, child: WidgetWithBackground( backgroundColor: textColor.withOpacity(0.25), // 原有的UI代码 ), );
如果需要保留OpenContainer的点击缩放动画,可继续用OpenContainer但禁用其路由跳转:
return OpenContainer<bool>( tappable: false, closedBuilder: (context, _) { return GestureDetector( onTap: () { GoRouter.of(context).pushNamed('categories'); }, child: WidgetWithBackground( backgroundColor: textColor.withOpacity(0.25), // 原有的UI代码 ), ); }, openBuilder: (context, _) => const SizedBox.shrink(), // 无需实际跳转路由 );
方案二:手动同步GoRouter location(不推荐,应急使用)
继续使用OpenContainer原生路由跳转,手动修改GoRouter的location,需注意路由栈同步问题:
修改_OpenContainerWrapper,在打开和关闭回调中同步location:
class _OpenContainerWrapper extends StatelessWidget { const _OpenContainerWrapper({ required this.closedBuilder, required this.transitionType, required this.onClosed, required this.page, this.routeSettings, this.borderRadius = 4, }); final CloseContainerBuilder closedBuilder; final ContainerTransitionType transitionType; final ClosedCallback<bool?> onClosed; final Widget page; final RouteSettings? routeSettings; final double borderRadius; @override Widget build(BuildContext context) { final GoRouter router = GoRouter.of(context); String? previousLocation; return OpenContainer<bool>( closedElevation: 0, closedColor: Colors.transparent, middleColor: Colors.transparent, openColor: Colors.transparent, routeSettings: routeSettings, closedShape: RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(borderRadius)), ), transitionType: transitionType, onOpen: () { previousLocation = router.location; if (routeSettings?.name != null) { router.replaceNamed(routeSettings!.name!); } }, openBuilder: (context, _) => page, onClosed: (result) { if (previousLocation != null) { router.replace(previousLocation!); } onClosed(result); }, tappable: false, closedBuilder: closedBuilder, ); } }
⚠️ 注意:该方案可能导致GoRouter路由栈与Navigator栈不一致,引发返回按钮行为异常,仅建议在无法重构路由逻辑时临时使用。
内容的提问来源于stack exchange,提问作者mirkancal
相关产品推荐
相关产品推荐

