flutter 拦截返回按钮的方法(WillPopScope or PopScope)

为了避免用户误触返回按钮而导致 App 退出,或者某些页面需要在退出时弹出二次确认弹窗,所以需要拦截返回按钮并进行自行处理。

1.在 flutter 3.12 以下 推荐使用 WillPopScope 组件来实现返回按钮的拦截(该组件在3.12已经被弃用); WillPopScope 的默认构造函数

dart 复制代码
const WillPopScope({
	required WillPopCallback onWillPop,
	required Widget child
})

onWillPop是一个回调函数,当用户点击返回按钮时被调用(包括导航返回按钮及Android的物理返回按钮,还有侧滑返回)。该回调需要返回一个 Future<bool>对象,如果返回的Future最终值为 false 时,则当前路由不出栈(不会返回); 最终值为true时,当前路由出栈退出。当我们使用这个组件的时候 通过这个回调来决定是否退出。

注意 : 如果使用 GetX 路由时在GetX 4.7.2 版本及以上时 WillPopScope 的侧滑返回会失效

WillPopScope 示例

为了防止用户误触返回按钮退出应用,我们拦截返回事件。当用户在1秒内点击两次返回按钮时,则退出;如果间隔超过1秒则不退出,并重新计时。代码如下:

scala 复制代码
import 'package:flutter/material.dart';  
class WillPopScopeTestRoute extends StatefulWidget {  
  WillPopScopeTestRoute({Key? key}) : super(key: key);  
  
  @override  
  State<WillPopScopeTestRoute> createState() => _WillPopScopeTestRouteState();  
}  
  
class _WillPopScopeTestRouteState extends State<WillPopScopeTestRoute>{  
  var lastClickTime = 0;  
  @override  
  Widget build(BuildContext context) {  
    return WillPopScope( onWillPop: ()async{  
      var nowTime = DateTime  
          .now()  
          .millisecondsSinceEpoch;  
      if(nowTime - lastClickTime < 1000 && lastClickTime != 0){  
        return true;  
      }  
      lastClickTime = nowTime;  
      return false;  
    },  
      child: Container(  
        alignment: Alignment.center,  
        child: const Text("1秒内连续按两次返回键退出"),  
      ),  
    );  
  }  
}

2.在 flutter 3.12 及以上 推荐使用 PopScope 组件来实现返回按钮的拦截; PopScope的默认构造函数

dart 复制代码
const PopScope({
  required Widget child,  
  bool canPop = true,  
  PopInvokedWithResultCallback? onPopInvokedWithResult
})

canPop 是一个 bool 值,设置为true 时不拦截,false 时拦截(包括导航返回按钮及Android的物理返回按钮,还有侧滑返回)。 onPopInvokedWithResult 是一个回调函数,在路由弹出后调用该函数。

dart 复制代码
typedef PopInvokedWithResultCallback<T> = void Function(bool didPop, T? result);

该回调函数有两个入参 didPoptrue 时返回键退出未拦截退出成功, 为 false 时返回键拦截未退出。 resultGet.back(result: "11"); 返回的 result 值。

注意 :如果使用 GetX 路由时在GetX 4.7.2 版本以下时 PopScope 的侧滑返回会失效

PopScope 示例

为了防止用户误触返回按钮退出应用,我们拦截返回事件。当用户在1秒内点击两次返回按钮时,则退出;如果间隔超过1秒则不退出,并重新计时。代码如下:

scala 复制代码
import 'package:flutter/material.dart';  
import 'package:get/get.dart';  
class WillPopScopeTestRoute extends StatefulWidget {  
  WillPopScopeTestRoute({Key? key}) : super(key: key);  
  
  @override  
  State<WillPopScopeTestRoute> createState() => _WillPopScopeTestRouteState();  
}  
  
class _WillPopScopeTestRouteState extends State<WillPopScopeTestRoute>{  
  var lastClickTime = 0;  
  @override  
  Widget build(BuildContext context) {  
    return PopScope(  
      canPop: false,  
      onPopInvokedWithResult: (didPop,result) async {  
        if(didPop){  
          //已经返回成功 就不用触发未拦截的逻辑了
          return ;  
        }  
        var nowTime = DateTime  
            .now()  
            .millisecondsSinceEpoch;  
        if (nowTime - lastClickTime < 1000 && lastClickTime != 0) {  
          Get.back();  
        }  
        lastClickTime = nowTime;  
      },  
      child: Container(  
        alignment: Alignment.center,  
        child: const Text("1秒内连续按两次返回键退出"),  
      ),  
    );  
  }  
}

关于 PopScope 在getX 4.7.2 版本以下 失效的原因请看 flutter getx 路由侧滑返回 PopScope 回调失效的探究与解决本文主要探讨了在基于 Getx 项目路由模 - 掘金

相关推荐
程序员Ctrl喵20 小时前
异步编程:Event Loop 与 Isolate 的深层博弈
开发语言·flutter
前端不太难21 小时前
Flutter 如何设计可长期维护的模块边界?
flutter
小蜜蜂嗡嗡1 天前
flutter列表中实现置顶动画
flutter
始持1 天前
第十二讲 风格与主题统一
前端·flutter
始持1 天前
第十一讲 界面导航与路由管理
flutter·vibecoding
始持1 天前
第十三讲 异步操作与异步构建
前端·flutter
新镜1 天前
【Flutter】 视频视频源横向、竖向问题
flutter
黄林晴1 天前
Compose Multiplatform 1.10 发布:统一 Preview、Navigation 3、Hot Reload 三箭齐发
android·flutter
Swift社区1 天前
Flutter 应该按功能拆,还是按技术层拆?
flutter
肠胃炎1 天前
树形选择器组件封装
前端·flutter