为了避免用户误触返回按钮而导致APP退出,在很多APP中都拦截了用户点击返回键的按钮,然后进行一些防误触判断,比如当用户在某一个时间段内点击两次时,才会认为用户是要退出(而非误触)。Flutter中可以通过WillPopScope 来实现返回按钮拦截,我们看看 WillPopScope 的默认构造函数:

    1. const WillPopScope({
    2. ...
    3. @required WillPopCallback onWillPop,
    4. @required Widget child
    5. })
    • onWillPop 是一个回调函数,我们需要提供这个回调来决定是否退出。当用户点击返回按钮时被调用(包括导航返回按钮及Android物理返回按钮)。该回调需要返回一个Future对象,如果返回的Future最终值为:
      • false,则当前路由不出栈(不会返回);
      • true,当前路由出栈退出。

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

    1. import 'package:flutter/material.dart';
    2. // import 'dart:math' as math;
    3. void main() => runApp(new MyApp());
    4. class MyApp extends StatelessWidget {
    5. @override
    6. Widget build(BuildContext context) {
    7. return MaterialApp(
    8. debugShowCheckedModeBanner: false,
    9. title: 'WillPopScopeTestRoute',
    10. theme: ThemeData(
    11. primarySwatch: Colors.blue,
    12. ),
    13. home: Scaffold(
    14. // appBar: AppBar(title: Text("滚动监听")),
    15. body: WillPopScopeTestRoute(),
    16. ));
    17. }
    18. }
    19. class WillPopScopeTestRoute extends StatefulWidget {
    20. @override
    21. WillPopScopeTestRouteState createState() {
    22. return new WillPopScopeTestRouteState();
    23. }
    24. }
    25. class WillPopScopeTestRouteState extends State<WillPopScopeTestRoute> {
    26. DateTime _lastPressedAt; //上次点击时间
    27. @override
    28. Widget build(BuildContext context) {
    29. return new WillPopScope(
    30. onWillPop: () async {
    31. if (_lastPressedAt == null ||
    32. DateTime.now().difference(_lastPressedAt) >
    33. Duration(seconds: 1)) {
    34. _lastPressedAt = DateTime.now(); //两次点击间隔超过1秒则重新计时
    35. return false;
    36. }
    37. return true;
    38. },
    39. child: Container(
    40. alignment: Alignment.center,
    41. child: Text("1秒内连续按两次返回键退出"),
    42. ));
    43. }
    44. }

    读者可以运行示例看看效果