You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 19:57:01