Flutter 3.16 中 WillPopScope 过期了,需要使用 PopScope 来代替。
针对 PopScope 的 canPop 参数,官方文档解释如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /// Manages system back gestures. /// /// The [canPop] parameter can be used to disable system back gestures. Defaults /// to true, meaning that back gestures happen as usual. /// /// The [onPopInvoked] parameter reports when system back gestures occur, /// regardless of whether or not they were successful. /// /// If [canPop] is false, then a system back gesture will not pop the route off /// of the enclosing [Navigator]. [onPopInvoked] will still be called, and /// `didPop` will be `false`. /// /// If [canPop] is true, then a system back gesture will cause the enclosing /// [Navigator] to receive a pop as usual. [onPopInvoked] will be called with /// `didPop` as `true`, unless the pop failed for reasons unrelated to /// [PopScope], in which case it will be `false`. | 
当 canPop 为 false,则执行系统返回时会被拦截,并且调用 onPopInvoked 方法,同时 didPop 为 false,此时进行逻辑判断,如果需要返回则执行 Navigator.of(context).pop(); 。
注意此时 onPopInvoked 又会被调用,并且 didPop 为 true。
参考Demo: github.com
示例代码如下:
修改之前的代码( WillPopScope )如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | // Copyright 2014 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This sample demonstrates showing a confirmation dialog before navigating // away from a page. import 'package:flutter/material.dart'; void main() => runApp(const NavigatorPopHandlerApp()); class NavigatorPopHandlerApp extends StatelessWidget {   const NavigatorPopHandlerApp({super.key});   @override   Widget build(BuildContext context) {     return MaterialApp(       initialRoute: '/home',       routes: <String, WidgetBuilder>{         '/home': (BuildContext context) => const _HomePage(),         '/two': (BuildContext context) => const _PageTwo(),       },     );   } } class _HomePage extends StatefulWidget {   const _HomePage();   @override   State<_HomePage> createState() => _HomePageState(); } class _HomePageState extends State<_HomePage> {   @override   Widget build(BuildContext context) {     return Scaffold(       body: Center(         child: Column(           mainAxisAlignment: MainAxisAlignment.center,           children: <Widget>[             const Text('Page One'),             TextButton(               onPressed: () {                 Navigator.of(context).pushNamed('/two');               },               child: const Text('Next page'),             ),           ],         ),       ),     );   } } class _PageTwo extends StatefulWidget {   const _PageTwo();   @override   State<_PageTwo> createState() => _PageTwoState(); } class _PageTwoState extends State<_PageTwo> {   void _showBackDialog() {     showDialog<void>(       context: context,       builder: (BuildContext context) {         return AlertDialog(           title: const Text('Are you sure?'),           content: const Text(             'Are you sure you want to leave this page?',           ),           actions: <Widget>[             TextButton(               style: TextButton.styleFrom(                 textStyle: Theme.of(context).textTheme.labelLarge,               ),               child: const Text('Nevermind'),               onPressed: () {                 Navigator.pop(context);               },             ),             TextButton(               style: TextButton.styleFrom(                 textStyle: Theme.of(context).textTheme.labelLarge,               ),               child: const Text('Leave'),               onPressed: () {                 Navigator.pop(context);                 Navigator.pop(context);               },             ),           ],         );       },     );   }   @override   Widget build(BuildContext context) {     return WillPopScope(         onWillPop: () {           _showBackDialog();           return false;         },         child: Scaffold(             body: Center(           child: Column(             mainAxisAlignment: MainAxisAlignment.center,             children: <Widget>[               const Text('Page Two'),               TextButton(                 onPressed: () {                   _showBackDialog();                 },                 child: const Text('Go back'),               ),             ],           ),         )));   } } | 
修改之后的代码( PopScope )如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | // Copyright 2014 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This sample demonstrates showing a confirmation dialog before navigating // away from a page. import 'package:flutter/material.dart'; void main() => runApp(const NavigatorPopHandlerApp()); class NavigatorPopHandlerApp extends StatelessWidget {   const NavigatorPopHandlerApp({super.key});   @override   Widget build(BuildContext context) {     return MaterialApp(       initialRoute: '/home',       routes: <String, WidgetBuilder>{         '/home': (BuildContext context) => const _HomePage(),         '/two': (BuildContext context) => const _PageTwo(),       },     );   } } class _HomePage extends StatefulWidget {   const _HomePage();   @override   State<_HomePage> createState() => _HomePageState(); } class _HomePageState extends State<_HomePage> {   @override   Widget build(BuildContext context) {     return Scaffold(       body: Center(         child: Column(           mainAxisAlignment: MainAxisAlignment.center,           children: <Widget>[             const Text('Page One'),             TextButton(               onPressed: () {                 Navigator.of(context).pushNamed('/two');               },               child: const Text('Next page'),             ),           ],         ),       ),     );   } } class _PageTwo extends StatefulWidget {   const _PageTwo();   @override   State<_PageTwo> createState() => _PageTwoState(); } class _PageTwoState extends State<_PageTwo> {   void _showBackDialog() {     showDialog<void>(       context: context,       builder: (BuildContext context) {         return AlertDialog(           title: const Text('Are you sure?'),           content: const Text(             'Are you sure you want to leave this page?',           ),           actions: <Widget>[             TextButton(               style: TextButton.styleFrom(                 textStyle: Theme.of(context).textTheme.labelLarge,               ),               child: const Text('Nevermind'),               onPressed: () {                 Navigator.pop(context);               },             ),             TextButton(               style: TextButton.styleFrom(                 textStyle: Theme.of(context).textTheme.labelLarge,               ),               child: const Text('Leave'),               onPressed: () {                 Navigator.pop(context);                 Navigator.pop(context);               },             ),           ],         );       },     );   }   @override   Widget build(BuildContext context) {     return Scaffold(       body: Center(         child: Column(           mainAxisAlignment: MainAxisAlignment.center,           children: <Widget>[             const Text('Page Two'),             PopScope(               canPop: false,               onPopInvoked: (bool didPop) {                 if (didPop) {                   return;                 }                 _showBackDialog();               },               child: TextButton(                 onPressed: () {                   _showBackDialog();                 },                 child: const Text('Go back'),               ),             ),           ],         ),       ),     );   } } |