Flutter 心得:PopScope 使用

7,376 阅读1分钟

Flutter 3.16 中 WillPopScope 已经被抛弃了,需要使用 PopScope 来代替。 PopScope的定义如下:

Widget PopScope({
    Key? key,   
    required Widget child,
    bool canPop = true,
    void Function( bool didPop )? onPopInvoked,
})

针对 PopScope 的 canPop 参数,官方文档解释如下:

canPoptrue,则系统返回手势将导致封闭的 Navigator 照常接收弹出。会调用 onPopInvoked,此时didPoptrue

当 canPop 为 false,则系统返回手势不会将路由从封闭的 Navigator 中弹出,但仍然会调用 onPopInvoked 方法,此时 didPop 为 false,此时进行逻辑判断或者插入其他需要执行的代码,如果需要返回则再执行 Navigator.of(context).pop();  。

注意此时 onPopInvoked 又会被再次调用,但此时 didPop 为 true

因此,在onPopInvoked中,需要判断一下 didPop,如果为 true, 则 return

示例代码:

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> {
  
  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      onPopInvoked: ( bool didPop ){
          if ( didPop ) return;         // really exit
          else {
            /* 
            Insert your code
            */
            
            Navigator.of(context).pop();
          }
      }
      child: Scaffold(
          body: Center(
            child: const Text('Page Two'),
          ),
       ),   
    );
  }
}