为了避免用户误触返回按钮而导致APP退出,在很多APP中都拦截了用户点击返回键的按钮,当用户在某一个时间段内点击两次时,才会认为用户是要退出(而非误触)。Flutter中可以通过WillPopScope来实现返回按钮拦截,我们看看WillPopScope的默认构造函数:
const WillPopScope({
...
@required WillPopCallback onWillPop,
@required Widget child
})
使用方式:
import 'package:flutter/material.dart';
class WillPopScopeTestRoute extends StatefulWidget {
@override
WillPopScopeTestRouteState createState() {
return new WillPopScopeTestRouteState();
}
}
class WillPopScopeTestRouteState extends State<WillPopScopeTestRoute> {
DateTime lastPopTime; //上次点击时间
@override
Widget build(BuildContext context) {
return new WillPopScope(
onWillPop: () async {
if (lastPopTime == null ||
DateTime.now().difference(lastPopTime) > Duration(seconds: 1)) {
//两次点击间隔超过1秒则重新计时
lastPopTime = DateTime.now();
return new Future.value(false);
}
return new Future.value(ture);
},
child: Container(
alignment: Alignment.center,
child: Text("再按一次退出"),
)
);
}
}
还有一种特殊的退出APP的方式,针对Android平台,在用户双击后APP退出前台,类似iOS在后台运行,实现如下。
1.在FLutter for Android 的MainActivity中:
package com.cgmcomm.cgmstore;
import android.app.Notification;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import com.cgmcomm.umeng.UmengGlobal;
import io.flutter.app.FlutterActivity;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class MainActivity extends FlutterActivity {
//通讯名称,回到手机桌面
private final String chanel = "back/desktop";
//返回手机桌面事件
static final String eventBackDesktop = "backDesktop";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//API>21,设置状态栏颜色透明
getWindow().setStatusBarColor(0);
}
GeneratedPluginRegistrant.registerWith(this);
initBackTop();
}
@Override
protected void onResume() {
super.onResume();
UmengGlobal.getInstance(this).onResume();
}
@Override
protected void onPause() {
super.onPause();
UmengGlobal.getInstance(this).onPause();
}
//注册返回到手机桌面事件
private void initBackTop() {
new MethodChannel(getFlutterView(), chanel).setMethodCallHandler(
(methodCall, result) -> {
if (methodCall.method.equals(eventBackDesktop)) {
moveTaskToBack(false);
result.success(true);
}
}
);
}
}
2.在FLutter中:
//android_back_desktop.dart
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
class AndroidBackTop {
///通讯名称,回到手机桌面
static const String chanel = "back/desktop";
//返回手机桌面事件
static const String eventBackDesktop = "backDesktop";
///设置回退到手机桌面
static Future<bool> backDesktop() async {
final platform = MethodChannel(chanel);
try {
await platform.invokeMethod(eventBackDesktop);
} on PlatformException catch (e) {
debugPrint(e.toString());
}
return Future.value(false);
}
}
//调用实例:
……
DateTime lastPopTime;
return WillPopScope(
child: Scaffold(
body: TabNavigator(
state: state,
dispatch: dispatch,
),
),
onWillPop: _doubleExit,
);
}
Future<bool> _doubleExit() async {
// 点击返回键的操作
if(lastPopTime == null || DateTime.now().difference(lastPopTime) > Duration(seconds: 2)){
lastPopTime = DateTime.now();
ToastTools.showToast("再按一次退出");
return new Future.value(false);
}else{
lastPopTime = DateTime.now();
// 退出app
return AndroidBackTop.backDesktop();
}
}