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
There is new property in PopScope named as canPop make it false to prevent back pop
PopScope(
canPop: false, —–> new
)
The behaviour you are getting is exactly what you coded.
In your
ElevatedButton
onPressed, you are callingNavigator.pop(context);
, that’s one.PopScope
has two parameters,canPop
andonPopInvoked
.PopScope
does not work likeWillPopScope
.WillPopScope
works by receiving a back navigation event and then deciding if it should proceed or abort. On the other handPopScope
knows beforehand whether or not back navigation should be allowed. This is to accommodate the Android Predictive Back FeatureYou 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 booleandidPop
in the callback. It is not for you to return true or false.You usually do something like:
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