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

Flutter WebView返回按钮逻辑异常:单次点击同时触发返回与提示

解决方案:Flutter WebView返回按钮逻辑修复

问题根源

原代码未区分WebView回退状态与应用退出逻辑,两个独立的if分支会在首次点击时同时触发回退操作与退出提示;同时使用全局变量维护状态,易引发多页面状态混乱。

修正代码

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:webview_flutter/webview_flutter.dart';

final uri = Uri.parse('https://google.com');

class HomeScreen extends StatefulWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  late WebViewController controller;
  int _backPressCount = 0;
  DateTime? _lastPressTime;

  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setNavigationDelegate(NavigationDelegate(
        onPageFinished: (String url) {
          print(url);
        },
      ))
      ..loadRequest(uri);
  }

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      onPopInvoked: (didPop) async {
        DateTime now = DateTime.now();

        // 优先处理WebView回退逻辑
        bool canGoBack = await controller.canGoBack();
        if (canGoBack) {
          controller.goBack();
          // 重置退出计数
          setState(() {
            _backPressCount = 0;
            _lastPressTime = null;
          });
          return;
        }

        // WebView无法回退时,处理应用退出逻辑
        if (_lastPressTime != null && now.difference(_lastPressTime!) > const Duration(seconds: 3)) {
          setState(() {
            _backPressCount = 0;
          });
        }

        setState(() {
          _backPressCount++;
          _lastPressTime = now;
        });

        if (_backPressCount == 2) {
          // 双击显示退出提示
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(
              content: Text('再点击一次退出应用'),
            ),
          );
        } else if (_backPressCount >= 3) {
          // 三次点击退出应用
          SystemNavigator.pop();
          exit(0);
        }
      },
      child: Scaffold(
        floatingActionButton: Container(
          height: 40.0,
          width: 40.0,
          child: FittedBox(
            child: FloatingActionButton(
              child: const Icon(Icons.arrow_back),
              onPressed: () async {
                bool canGoBack = await controller.canGoBack();
                if (canGoBack) {
                  controller.goBack();
                  setState(() {
                    _backPressCount = 0;
                    _lastPressTime = null;
                  });
                } else {
                  // 触发系统返回逻辑
                  Navigator.maybePop(context);
                }
              },
              backgroundColor: Colors.grey.shade200,
            ),
          ),
        ),
        body: SafeArea(
          child: WebViewWidget(
            controller: controller,
          ),
        ),
      ),
    );
  }
}

关键修改点

  • 状态管理优化:将StatelessWidget改为StatefulWidget,使用状态变量_backPressCount和_lastPressTime维护点击状态,避免全局变量污染。
  • 逻辑优先级调整:先判断WebView是否可回退,仅当无法回退时才处理应用退出逻辑,彻底解决单击时回退与提示同时触发的问题。
  • 退出逻辑明确:
    • WebView可回退:单击返回上一页,重置退出计数。
    • WebView不可回退:第一次单击无提示,第二次单击显示退出提示,第三次单击(3秒内)退出应用。
  • 浮动按钮同步逻辑:自定义返回按钮与系统返回按钮行为保持一致,确保交互统一。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 10:05:18