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

Flutter底部导航栏场景下WebView页面返回按键控制实现问题

修复方案

你遇到的问题核心有两个:

  1. 两个标签页都属于首页同一个路由下的子组件,只有外层首页的WillPopScope会响应返回事件,WebView页的WillPopScope根本不会被触发
  2. 原有WebView的返回逻辑返回值写反,且缺少空安全判断

第一步:修改WebView页(WatchPage)代码

// 注意State类要改为公开(去掉下划线),方便父页面调用
class WatchPage extends StatefulWidget {
  // 保留你原有构造方法即可
  const WatchPage({super.key});

  @override
  State<WatchPage> createState() => WatchPageState();
}

class WatchPageState extends State<WatchPage> {
  WebViewController? controller; // 改为可空类型避免空报错
  final Completer<WebViewController> _controller =
      Completer<WebViewController>();

  // 公开的返回事件处理方法,供首页调用
  Future<bool> handleBack() async {
    if (controller != null && await controller!.canGoBack()) {
      controller!.goBack();
      // 返回false表示已经处理返回事件,不需要上层再响应
      return false;
    }
    // 返回true表示WebView无法回退,需要上层处理
    return true;
  }

  @override
  Widget build(BuildContext context) {
    // 去掉这里的WillPopScope,同路由下不会触发
    return Scaffold(
      appBar: AppBar(
        toolbarHeight: 10,
        flexibleSpace: Container(
          color: const Color(0xff1f5269),
        ),
      ),
      body: Builder(builder: (BuildContext context) {
        return WebView(
          initialUrl: widget.text,
          javascriptMode: JavascriptMode.unrestricted,
          onWebViewCreated: (WebViewController c) {
            controller = c; // 直接赋值即可,原有future逻辑冗余
            _controller.complete(c);
          },
          onProgress: (int progress) {},
          onPageStarted: (String url) {
            if (url == "https://app.testt.com/Login/Cikis") {
              Navigator.of(context, rootNavigator: true).push(
                  MaterialPageRoute(builder: (context) => const LoginPage()));
            }
          },
          onPageFinished: (String url) {
            if (url == "https://app.testt.com/Login" ) {
              Navigator.of(context, rootNavigator: true).push(
                  MaterialPageRoute(builder: (context) => const LoginPage()));
            }
          },
          gestureNavigationEnabled: true,
        );
      }),
    );
  }
}

第二步:修改首页代码

// 声明GlobalKey用来获取WebView页的状态
final GlobalKey<WatchPageState> _watchPageKey = GlobalKey<WatchPageState>();

Future<bool> _onBackPressed() async {
  // 先判断当前是否在WebView标签页
  if (_activePage == 1) {
    bool needParentHandle = await _watchPageKey.currentState?.handleBack() ?? true;
    if (!needParentHandle) {
      // WebView已经处理了回退,直接拦截返回事件
      return false;
    }
  }
  // 原生页面/ WebView无法回退时,弹出退出确认框
  return await (showDialog(
        context: context,
        builder: (context) => AlertDialog(
          title: const Text('Sure?'),
          content: const Text('???'),
          actions: <Widget>[
            TextButton(
              onPressed: () => Navigator.of(context).pop(false),
              child: const Text('No'),
            ),
            TextButton(
              onPressed: () => Navigator.of(context).pop(true),
              child: const Text('Yes'),
            ),
          ],
        ),
      )) ??
      false;
}

@override
Widget build(BuildContext context) {
  List<Widget> pageList = [
    MainHomePage(
      text: widget.text,
    ),
    // 给WebView页传入GlobalKey
    WatchPage(key: _watchPageKey)
  ];
  return WillPopScope(
    onWillPop: _onBackPressed,
    child: Scaffold(
      body: Container(
        child: pageList[_activePage],
      ),
      bottomNavigationBar: CurvedNavigationBar(
        animationCurve: Curves.easeInOut,
        animationDuration: const Duration(milliseconds: 600),
        color: const Color(0xff1f5269),
        backgroundColor: Colors.transparent,
        onTap: (index) {
          setState(() {
            _activePage = index;
          });
        },
        items: <Widget>[
          const Icon(
            Icons.home,
            color: Colors.white,
          ),
          const Icon(
            Icons.tv,
            color: Colors.white,
          ),
        ],
      ),
    ),
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 02:09:04