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

如何在Flutter的Modal Bottom Sheet内嵌入支付网页,避免打开外部页面?

解决Flutter Modal Bottom Sheet内显示支付WebView的问题

问题根源

你当前使用的launchUrl方法,本质就是调用系统默认浏览器/应用打开外部链接,所以必然会跳转到外部页面,这就是核心问题所在。

解决方案

要在Bottom Sheet内嵌入支付页面,需要使用Flutter官方的webview_flutter插件,直接将网页嵌入模态框中,替换掉launchUrl的跳转逻辑。

步骤1:添加依赖

在项目的pubspec.yaml中添加webview_flutter依赖:

dependencies:
  flutter:
    sdk: flutter
  webview_flutter: ^4.4.0 # 可替换为最新版本

执行flutter pub get完成依赖安装。

步骤2:修改代码替换跳转逻辑

把原代码中的FutureBuilder和launchUrl替换为WebView组件,调整布局让网页占满模态框的剩余空间,同时保留加载状态控制:

await showModalBottomSheet(
  elevation: 10,
  backgroundColor: Colors.transparent,
  isScrollControlled: true,
  context: context,
  builder: (context) {
    // 用StatefulBuilder管理加载状态
    return StatefulBuilder(
      builder: (context, setState) {
        bool isLoading = true;
        return Container(
          decoration: const BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.only(
              topLeft: Radius.circular(30),
              topRight: Radius.circular(30),
            ),
          ),
          height: MediaQuery.of(context).size.height * 0.9,
          child: Column(
            children: [
              // 顶部关闭按钮
              Padding(
                padding: EdgeInsets.only(
                  top: MediaQuery.of(context).size.height * 0.03,
                  left: MediaQuery.of(context).size.width * 0.05,
                ),
                child: Row(
                  children: [
                    Container(
                      height: 40,
                      width: 40,
                      decoration: BoxDecoration(
                        color: AppColors.drawerTextListTileColor,
                        borderRadius: BorderRadius.circular(10),
                      ),
                      child: IconButton(
                        onPressed: () {
                          Navigator.of(context).pop();
                        },
                        icon: const Icon(Icons.close, color: Colors.white),
                      ),
                    ),
                    const Spacer(),
                  ],
                ),
              ),
              // 用Expanded让WebView占满剩余空间
              Expanded(
                child: Stack(
                  children: [
                    WebView(
                      initialUrl: resultParsed.topUpWallet.url,
                      javascriptMode: JavascriptMode.unrestricted, // 支付页面需开启JS支持
                      onPageStarted: (url) {
                        setState(() => isLoading = true);
                      },
                      onPageFinished: (url) {
                        setState(() => isLoading = false);
                      },
                      // 拦截导航,防止跳转到外部浏览器
                      navigationDelegate: (NavigationRequest request) {
                        // 只允许支付域名下的链接在WebView内打开
                        if (request.url.startsWith('https://你的支付域名前缀')) {
                          return NavigationDecision.navigate;
                        }
                        // 其他链接禁止跳转,可根据需求调整
                        return NavigationDecision.prevent;
                      },
                    ),
                    // 加载状态指示器
                    if (isLoading)
                      const Center(child: CircularProgressIndicator()),
                  ],
                ),
              ),
            ],
          ),
        );
      },
    );
  },
);

关键说明

  • WebView替代launchUrl:直接将支付页面嵌入App内部,完全避免外部跳转。
  • Expanded布局:确保WebView占满模态框除顶部按钮外的所有可用空间。
  • JavaScript支持:绝大多数支付页面依赖JavaScript,必须设置JavascriptMode.unrestricted。
  • 导航拦截:通过navigationDelegate控制页面跳转,确保支付流程全程在WebView内完成。

内容的提问来源于stack exchange,提问作者Farid Ahmadov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 16:13:22