flutter 再按一次退出 导航返回拦截WillPopScope

为了避免用户误触返回按钮而导致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();
  }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

倚栏静望

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值