How to write a double back button pressed to exit app using flutter

前端 未结 9 474
野趣味
野趣味 2020-12-24 13:39

I\'m new to flutter, and I saw many android apps can exit when double press back button.

The first time press back button, app shows a toast\"press again to exit app

相关标签:
9条回答
  • 2020-12-24 14:28

    This is my answer. I used AlertDialog() to achieve this

     @override
      Widget build(BuildContext context) {
        return new WillPopScope(
          onWillPop: _onBackPressed,
          child: Scaffold(
            appBar: AppBar(),
            body: Container(),
          ),
        );
      }
      Future<bool> _onBackPressed() {
        return showDialog(
          context: context,
          builder: (context) {
            return AlertDialog(
              title: Text('Confirm'),
              content: Text('Do you want to exit the App'),
              actions: <Widget>[
                FlatButton(
                  child: Text('No'),
                  onPressed: () {
                    Navigator.of(context).pop(false); //Will not exit the App
                  },
                ),
                FlatButton(
                  child: Text('Yes'),
                  onPressed: () {
                    Navigator.of(context).pop(true); //Will exit the App
                  },
                )
              ],
            );
          },
        ) ?? false;
      }
    
    0 讨论(0)
  • 2020-12-24 14:30

    Unfortunately none of them worked for me, I have written one generic class (widget) to handle double tap exit. If someone is interested

    class DoubleBackToCloseWidget extends StatefulWidget {
      final Widget child; // Make Sure this child has a Scaffold widget as parent.
    
      const DoubleBackToCloseWidget({
        @required this.child,
      });
    
      @override
      _DoubleBackToCloseWidgetState createState() =>
          _DoubleBackToCloseWidgetState();
    }
    
    class _DoubleBackToCloseWidgetState extends State<DoubleBackToCloseWidget> {
      int _lastTimeBackButtonWasTapped;
      static const exitTimeInMillis = 2000;
    
      bool get _isAndroid => Theme.of(context).platform == TargetPlatform.android;
    
      @override
      Widget build(BuildContext context) {
        if (_isAndroid) {
          return WillPopScope(
            onWillPop: _handleWillPop,
            child: widget.child,
          );
        } else {
          return widget.child;
        }
      }
    
      Future<bool> _handleWillPop() async {
        final _currentTime = DateTime.now().millisecondsSinceEpoch;
    
        if (_lastTimeBackButtonWasTapped != null &&
            (_currentTime - _lastTimeBackButtonWasTapped) < exitTimeInMillis) {
          Scaffold.of(context).removeCurrentSnackBar();
          return true;
        } else {
          _lastTimeBackButtonWasTapped = DateTime.now().millisecondsSinceEpoch;
          Scaffold.of(context).removeCurrentSnackBar();
          Scaffold.of(context).showSnackBar(
            _getExitSnackBar(context),
          );
          return false;
        }
      }
    
      SnackBar _getExitSnackBar(
        BuildContext context,
      ) {
        return SnackBar(
          content: Text(
            'Press BACK again to exit!',
            color: Colors.white,
          ),
          backgroundColor: Colors.red,
          duration: const Duration(
            seconds: 2,
          ),
          behavior: SnackBarBehavior.floating,
        );
      }
    }
    
    

    Use this class following way:

    class Dashboard extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return SafeArea(
          child: Scaffold(
            body: DoubleBackToCloseWidget(
              child: Container(
                child: Column(
                  children: [
                    const Text('Hello there'),
                    const Text('Hello there again'),
                  ],
                ),
              ),
            ),
          ),
        );
      }
    }
    
    
    
    0 讨论(0)
  • 2020-12-24 14:31

    If you want a snackbar you should provide a scaffold key as it's related to a scaffold, so this key should make the trick of calling a snackbar outside of it's scaffold parent.

    Here is a solution :

    class Home extends StatelessWidget {
    
      final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
    
      @override
      Widget build(BuildContext context) {
      return WillPopScope(
        onWillPop: () async{
            DateTime initTime = DateTime.now();
            popped +=1;
            if(popped>=2) return true;
            await _scaffoldKey.currentState.showSnackBar(
            SnackBar(
                behavior: SnackBarBehavior.floating,
                content: Text('Tap one more time to exit.',textAlign: TextAlign.center,),
                duration: Duration(seconds: 2),
            )).closed;
    
            // if timer is > 2 seconds reset popped counter
            if(DateTime.now().difference(initTime)>=Duration(seconds: 2)) {
            popped = 0;
            }
            return false;
            },
        child: Scaffold(
            key: _scaffoldKey,
            appBar: AppBar(title : Text("Demo")),
            body: Text("body")
        );
      )
    }
    
    
    0 讨论(0)
提交回复
热议问题