8

How can I handle device back button's onPressed() in Flutter for Android? I know that I must put a back button manually for iOS but Android device has built-in BACK button and user can press it. How to handle that?

PrakashG
  • 1,642
  • 5
  • 20
  • 30
Mohsen Emami
  • 2,709
  • 3
  • 33
  • 40
  • what do you mean by handle what specific action do you want to perform on it? – Amit Jangid Feb 16 '19 at 07:05
  • I'm using Scaffold in my main page and its **body** is filled (changed) by tapping on Drawer items, then when I press device back button on every **sub-page** (actually fragment) exits application or goes to incorrect page? I want to handle it manually but I'm not sure this approach is true – Mohsen Emami Feb 16 '19 at 07:20

2 Answers2

12

You can use WillPopScope to achieve this.

Firstly wrap your Scaffold inside WillPopScope. I'm showing a dialog at the first page to ask confirmation for exiting the app. You can modify this according to your need.

Example:

@override
  Widget build(BuildContext context) {
    return new WillPopScope(
      child: Scaffold(
          backgroundColor: Color.fromRGBO(255, 255, 255, 20.0),
          resizeToAvoidBottomPadding: true,
          appBar: AppBar(
              elevation: 4.0,
              title:
                  Text('Dashbaord', style: Theme.of(context).textTheme.title),
              leading: new IconButton(
                icon: new Icon(Icons.arrow_back, color: Colors.white),
                onPressed: () => _onWillPop(),
              )),
          body: new Container(), // your body content
      onWillPop: _onWillPop,
    );
  }

 // this is the future function called to show dialog for confirm exit.
 Future<bool> _onWillPop() {
    return showDialog(
          context: context,
          builder: (context) => new AlertDialog(
                title: new Text('Confirm Exit?',
                    style: new TextStyle(color: Colors.black, fontSize: 20.0)),
                content: new Text(
                    'Are you sure you want to exit the app? Tap \'Yes\' to exit \'No\' to cancel.'),
                actions: <Widget>[
                  new FlatButton(
                    onPressed: () {
                      // this line exits the app.
                      SystemChannels.platform
                            .invokeMethod('SystemNavigator.pop');
                    },
                    child:
                        new Text('Yes', style: new TextStyle(fontSize: 18.0)),
                  ),
                  new FlatButton(
                    onPressed: () => Navigator.pop(context), // this line dismisses the dialog
                    child: new Text('No', style: new TextStyle(fontSize: 18.0)),
                  )
                ],
              ),
        ) ??
        false;
  }
}

In the above example I'm calling this _onWillPop() function when the user hits the BACK button and the back button in AppBar.

You can use this WillPopScope to achieve the BACK button press and perform action you want to.

Amit Jangid
  • 2,741
  • 1
  • 22
  • 28
  • your solution was useful for my app and my be the correct answer of my question, but now I want to know what is the reason of what is happening in my sub-pages? – Mohsen Emami Feb 16 '19 at 07:56
  • Another question: why have you made the return value Future in this case? Thanks :-| – Mohsen Emami Feb 16 '19 at 08:01
  • what if you want to pass data to the previous page on back button pressed ? I have already tried adding the data to the backbutton on the app bar and it works but back button in app bar code is not called when the physical android back button is pressed – crushman Oct 04 '20 at 16:31
  • You can use navigator for passing data back... Ex: Navigator.pop(context, 'dataToBePassed'); – Amit Jangid Oct 05 '20 at 11:25
  • Please note, this will not work if using Navigator 2.0 or GoRouter as onWillPop is not longer recognised in this way. See here: https://medium.com/codex/flutter-case-study-catching-back-button-presses-on-android-when-using-navigator-2-0-d4d42e4718f6 – Delmontee Jan 10 '23 at 13:44
0

You can use WillPopScope to achieve this.

Example code:

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:get/get.dart';

import 'widget/appbar.dart';

class TestScreen extends StatelessWidget {
  static const String id = 'TestScreen';

  bool isDoublePress = false;

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
        onWillPop: onWillPop,
        child: Scaffold(
          body: Text('Back press handle'),
        ));
  }

  Future<bool> onWillPop() {
    if (isDoublePress) {
      return Future.value(true);
    } else {
      Get.snackbar('Warning!', 'Press again to exit');
      isDoublePress = true;
      Timer(const Duration(seconds: 3), () => isDoublePress = false);
      return Future.value(false);
    }
  }
}

if you didn't user Getx library then use the get on pubspec.yaml

  #Getx library
  get: ^4.6.5