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'), ), ), ], ), ), ); } } |