skip to Main Content

Using Flutter 3.16.3 with Dart 3.2.3 DevTools 2.28.4
If I am using PopScope after pressing the ‘Press Me’ ElevatedButton (before Future is ended), a black screen is displayed.
When using WillPopScope everything is working as expected.

What I would like to accomplished is to use PopScope for displaying progressDialogue on ‘Press Me’ ElevatedButton so I will work like using WillPopScope.

Here is my code:

import 'dart:async';

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

// This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  @override
  build(BuildContext context) {
    return Scaffold(
        body: Center(
      child: ElevatedButton(
        onPressed: () async {
          progressDialogue(context);

          final futureResults = await simulateFuture();
          debugPrint(futureResults);

          Navigator.pop(context);
        },
        child: const Text('Press Me'),
      ),
    ));
  }
}

Future<String> simulateFuture() {
  Completer<String> completer = Completer<String>();

// Simulating an asynchronous task after 2 seconds
  Future.delayed(const Duration(seconds: 5), () {
    // Completing the Future with a value after the task is done
    completer.complete('Simulated Future Result');
  });

  return completer.future;
}

progressDialogue(BuildContext context) {
//set up the AlertDialog
  AlertDialog alert = const AlertDialog(
    backgroundColor: Colors.transparent,
    elevation: 0,
    content: Center(
      child: CircularProgressIndicator(),
    ),
  );
  showDialog(
    //prevent outside touch
    barrierDismissible: false,
    context: context,
    builder: (BuildContext context) {
      //prevent Back button press
      //return WillPopScope(onWillPop: () async => false, child: alert);
      return PopScope(onPopInvoked: (didpop) async => false, child: alert);
    },
  );
}

2

Answers


  1. There is new property in PopScope named as canPop make it false to prevent back pop

    PopScope(
    canPop: false, —–> new

    )

    Login or Signup to reply.
  2. The behaviour you are getting is exactly what you coded.

    In your ElevatedButton onPressed, you are calling Navigator.pop(context);, that’s one.

    PopScope has two parameters, canPop and onPopInvoked.

    PopScope does not work like WillPopScope.

    WillPopScope works by receiving a back navigation event and then deciding if it should proceed or abort. On the other hand

    PopScope knows beforehand whether or not back navigation should be allowed. This is to accommodate the Android Predictive Back Feature

    You can allow or block back navigation with the canPop property which is simply a boolean, so it knows beforehand if it should allow back navigation.
    By default canPop is set to true, which is why you are getting that experience; you are popping twice when there is only one route in the Navigation stack.

    onPopInvoked is mainly for you to take some action based on whether pop was allowed or not, that is why you have a boolean didPop in the callback. It is not for you to return true or false.

    You usually do something like:

     onPopInvoked: (bool didPop) async {
        if (didPop) {
         // If back navigation was allowed, do nothing.
          return;
        }
         
        // If it was not allowed, do this
        final NavigatorState navigator = Navigator.of(context);
        final bool? shouldPop = await _showBackDialog();
        if (shouldPop ?? false) {
          navigator.pop();
        }
      },
    

    If you still need further clarification, this is a good read:
    https://docs.flutter.dev/release/breaking-changes/android-predictive-back

    You can go directly to this section:
    https://docs.flutter.dev/release/breaking-changes/android-predictive-back#migrating-a-back-confirmation-dialog

    You can also look at the PopScope api
    https://api.flutter.dev/flutter/widgets/PopScope-class.html

    Hope this was helpful

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search