Flutter Web基于Beamer实现带URL路由可入导航栈的弹窗方案咨询
Flutter Web 基于Beamer实现带独立路由的弹窗方案
要实现Twitter发推式的弹窗路由,本质是在原有页面栈上叠加一层透明的弹窗路由,Beamer的Page栈机制可以完美支持这一需求,不需要修改原有路由结构,具体实现步骤如下:
步骤1:配置路由规则,新增弹窗独立路径
在你项目的BeamLocation实现类中,新增弹窗的路径规则,将弹窗对应的BeamPage设置为非透明,确保下层页面可见:
class AppLocation extends BeamLocation<BeamState> { @override List<Pattern> get pathPatterns => [ '/home', '/compose/tweet', // 发推弹窗的独立路径 ]; @override List<BeamPage> buildPages(BuildContext context, BeamState state) { final pages = [ const BeamPage( key: ValueKey('home'), child: HomeScreen(), ), ]; // 匹配到发推路由时,将弹窗页追加到栈顶 if (state.uri.path == '/compose/tweet') { pages.add( BeamPage( key: const ValueKey('compose-tweet'), // 核心配置:页面透明,透出下层原有页面 opaque: false, // 可自定义转场动画,不需要动画就用NoAnimationTransitionDelegate transitionDelegate: const NoAnimationTransitionDelegate(), child: const ComposeTweetDialog(), ), ); } return pages; } }
核心配置说明:
- 必须将弹窗页的
opaque属性设为false,才不会遮挡下层的原有页面- 路径和普通页面平级,刷新页面时Beamer会自动按顺序构建栈,底层页面+弹窗同时加载
步骤2:实现弹窗组件,绑定回退逻辑
弹窗组件本身是全屏半透明结构,点击蒙层、关闭按钮、发布操作都调用Beamer的回退方法即可同步关闭弹窗和更新路由:
class ComposeTweetDialog extends StatelessWidget { const ComposeTweetDialog({super.key}); @override Widget build(BuildContext context) { return GestureDetector( // 点击蒙层区域触发回退,关闭弹窗 onTap: () => Beamer.of(context).beamBack(), child: Scaffold( // 半透明背景模拟弹窗蒙层 backgroundColor: Colors.black54, body: Center( child: GestureDetector( // 拦截弹窗内容区域的点击事件,避免误触关闭 onTap: () {}, child: Container( width: 600, padding: const EdgeInsets.all(24), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text('发推文', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), IconButton( // 关闭按钮触发回退 onPressed: () => Beamer.of(context).beamBack(), icon: const Icon(Icons.close), ) ], ), const TextField(maxLines: 6, decoration: InputDecoration(hintText: '分享你的想法...')), const SizedBox(height: 16), ElevatedButton(onPressed: () { // 发布成功后触发回退关闭弹窗 Beamer.of(context).beamBack(); }, child: const Text('发布')) ], ), ), ), ), ), ); } }
步骤3:调用跳转逻辑
业务侧触发弹窗时,直接调用Beamer的命名路由跳转即可:Beamer.of(context).beamToNamed('/compose/tweet');
效果验证
所有需求都可以满足:
- 直接访问对应URL,会自动唤起弹窗,且下层页面正常显示
- 弹窗打开后地址栏同步对应路由,加入浏览器历史栈
- 点击浏览器回退、系统返回手势、调用
beamBack方法都可以关闭弹窗,路由回退到上一级
可选优化:自定义弹窗动画
如果需要弹窗从底部弹出的动效,自定义TransitionDelegate并替换BeamPage的对应属性即可,代码示例:
class DialogTransitionDelegate extends TransitionDelegate { const DialogTransitionDelegate(); @override Iterable<RouteTransitionRecord> resolve({ required List<RouteTransitionRecord> newPageRouteHistory, required Map<RouteTransitionRecord?, RouteTransitionRecord> locationToExitingPageRoute, required Map<RouteTransitionRecord?, List<RouteTransitionRecord>> pageRouteToPagelessRoutes, }) { final results = <RouteTransitionRecord>[]; for (final pageRoute in newPageRouteHistory) { if (pageRoute.isWaitingForEnteringDecision) { pageRoute.markForPush(); } results.add(pageRoute); } for (final exitingPageRoute in locationToExitingPageRoute.values) { if (exitingPageRoute.isWaitingForExitingDecision) { exitingPageRoute.markForPop(); } results.add(exitingPageRoute); } return results; } }
搭配BeamPage的transitionBuilder属性即可自定义具体的动效曲线。
内容的提问来源于stack exchange,提问作者Whao Liang
相关产品推荐
相关产品推荐

