为了避免用户误触返回按钮而导致 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);
该回调函数有两个入参 didPop
为 true
时返回键退出未拦截退出成功, 为 false
时返回键拦截未退出。 result
是 Get.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 项目路由模 - 掘金