flutter [Popscope, NavigatorPopHandler] 每个PopScope都会被触发,而不是可见/活动的其中一个,

f1tvaqid  于 2个月前  发布在  Flutter
关注(0)|答案(1)|浏览(45)

重现步骤

  1. 在Android上运行代码(更容易重现)
  2. 停留在主页
  3. 按设备返回键(或滑动以弹出)
  4. 查看日志

预期结果

I/flutter (31191): [LabeledGlobalKey<NavigatorState>#fb408 home] onPop

实际结果

I/flutter (31191): Are you sure to leave the app ?
I/flutter (31191): [LabeledGlobalKey<NavigatorState>#fb408 home] onPop
I/flutter (31191): [LabeledGlobalKey<NavigatorState>#08a9b notification] onPop
I/flutter (31191): [LabeledGlobalKey<NavigatorState>#d0ebc message] onPop

由于这个原因,我无法仅弹出嵌套的可见页面。我使用IndexedStack并行和保持我的页面活跃。

代码示例

代码示例

import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Home(),
    );
  }
}

class Home extends StatefulWidget {
  const Home({super.key});

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  final GlobalKey<NavigatorState> _homeKey = GlobalKey<NavigatorState>(debugLabel: "home");
  final GlobalKey<NavigatorState> _notificationKey = GlobalKey<NavigatorState>(debugLabel: "notification");
  final GlobalKey<NavigatorState> _messageKey = GlobalKey<NavigatorState>(debugLabel: "message");

  int index = 0;

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      onPopInvoked: (bool didPop) {
        if (didPop) return;
        debugPrint("Are you sure to leave the app ?");
      },
      child: Scaffold(
        appBar: AppBar(
          title: const Text('Home'),
        ),
        body: IndexedStack(
          index: index,
          children: <Widget>[
            Nested(
              color: Colors.orange,
              navigationKey: _homeKey,
            ),
            Nested(
              color: Colors.blue,
              navigationKey: _notificationKey,
            ),
            Nested(
              color: Colors.green,
              navigationKey: _messageKey,
            ),
          ],
        ),
        bottomNavigationBar: NavigationBar(
          selectedIndex: index,
          onDestinationSelected: (int index) {
            setState(() => this.index = index);
          },
          destinations: const <Widget>[
            NavigationDestination(
              selectedIcon: Icon(Icons.home),
              icon: Icon(Icons.home_outlined),
              label: 'Home',
            ),
            NavigationDestination(
              icon: Icon(Icons.notifications_sharp),
              label: 'Notifications',
            ),
            NavigationDestination(
              icon: Icon(Icons.messenger_sharp),
              label: 'Messages',
            ),
          ],
        ),
      ),
    );
  }
}

class Nested extends StatelessWidget {
  const Nested({
    required this.navigationKey,
    required this.color,
    super.key,
  });

  final GlobalKey<NavigatorState> navigationKey;
  final Color color;

  @override
  Widget build(BuildContext context) {
    return NavigatorPopHandler(
      onPop: () {
        print("$navigationKey onPop");
        navigationKey.currentState?.maybePop();
      },
      child: Navigator(
        key: navigationKey,
        initialRoute: '/',
        onGenerateRoute: (RouteSettings settings) {
          return switch (settings.name) {
            '/' => MaterialPageRoute(
                builder: (BuildContext context) {
                  return Container(
                    color: color,
                    child: const FakeFirstPage(),
                  );
                },
              ),
            '/increment' => MaterialPageRoute(
                builder: (BuildContext context) {
                  return Container(
                    color: color.withGreen(color.green + 50),
                    child: const FakeSecondPage(),
                  );
                },
              ),
            _ => null,
          };
        },
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          ElevatedButton(
            onPressed: () {
              Navigator.of(context).pushNamed("/increment");
            },
            child: const Text("Go to second page"),
          ),
        ],
      ),
    );
  }
}

class FakeSecondPage extends StatefulWidget {
  const FakeSecondPage({super.key});

  @override
  State<FakeSecondPage> createState() => _FakeSecondPageState();
}

class _FakeSecondPageState extends State<FakeSecondPage> {
  int nb = 0;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          ElevatedButton(
            onPressed: () {
              setState(() => nb++);
            },
            child: const Text("Increment"),
          ),
          Text(nb.toString()),
        ],
      ),
    );
  }
}

截图或视频

截图/视频演示Screen_recording_20240724_112648.mp4

日志

日志

[Paste your logs here]

Flutter Doctor输出

Doctor输出

[✓] Flutter (Channel stable, 3.22.3, on macOS 14.5 23F79 darwin-arm64, locale fr-FR)
• Flutter version 3.22.3 on channel stable at /Users/earminjon/fvm/versions/3.22.3
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision b0850beeb2 (7 days ago), 2024-07-16 21:43:41 -0700
• Engine revision 235db911ba
• Dart version 3.4.4
• DevTools version 2.34.3

[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
• Android SDK at /Users/earminjon/Library/Android/Sdk
• Platform android-35, build-tools 35.0.0
• ANDROID_HOME = /Users/earminjon/Library/Android/Sdk
• Java binary at: /Users/earminjon/Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 17.0.10+0-17.0.10b1087.21-11609105)
• All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 15.4)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 15F31d
• CocoaPods version 1.14.3

[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2024.1)
• Android Studio at /Users/earminjon/Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 17.0.10+0-17.0.10b1087.21-11609105)

[✓] Android Studio (version 2023.2)
• Android Studio at /Users/perso/Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 17.0.9+0-17.0.9b1087.7-11185874)

[✓] IntelliJ IDEA Ultimate Edition (version 2023.3.7)
• IntelliJ at /Users/earminjon/Applications/IntelliJ IDEA Ultimate 2023.3.7.app
• Flutter plugin version 80.0.1
• Dart plugin version 233.15325.11

[✓] Connected device (4 available)
• sdk gphone64 arm64 (mobile)     • emulator-5554         • android-arm64  • Android 14 (API 34) (emulator)
• macOS (desktop)                 • macos                 • darwin-arm64   • macOS 14.5 23F79 darwin-arm64
• Mac Designed for iPad (desktop) • mac-designed-for-ipad • darwin         • macOS 14.5 23F79 darwin-arm64
• Chrome (web)                    • chrome                • web-javascript • Google Chrome 126.0.6478.183

[✓] Network resources
• All expected network resources are available.

• No issues found!
3xiyfsfu

3xiyfsfu1#

Reproducible using the code sample & steps provided above.
flutter doctor -v

[!] Flutter (Channel stable, 3.22.3, on macOS 14.4.1 23E224 darwin-arm64, locale en-GB)
    • Flutter version 3.22.3 on channel stable at /Users/nexus/dev/sdks/flutter
    ! Warning: `flutter` on your path resolves to /Users/nexus/dev/sdks/flutters/bin/flutter, which is not inside your current Flutter SDK checkout at /Users/nexus/dev/sdks/flutter. Consider adding /Users/nexus/dev/sdks/flutter/bin to the front of your path.
    ! Warning: `dart` on your path resolves to /Users/nexus/dev/sdks/flutters/bin/dart, which is not inside your current Flutter SDK checkout at /Users/nexus/dev/sdks/flutter. Consider adding /Users/nexus/dev/sdks/flutter/bin to the front of your path.
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision b0850beeb2 (7 days ago), 2024-07-16 21:43:41 -0700
    • Engine revision 235db911ba
    • Dart version 3.4.4
    • DevTools version 2.34.3
    • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades.
[✓] Flutter (Channel master, 3.24.0-1.0.pre.245, on macOS 14.4.1 23E224 darwin-arm64, locale en-GB)
    • Flutter version 3.24.0-1.0.pre.245 on channel master at /Users/nexus/dev/sdks/flutters
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision d4124bd5b5 (7 hours ago), 2024-07-24 00:10:30 -0400
    • Engine revision 1572635432
    • Dart version 3.6.0 (build 3.6.0-75.0.dev)
    • DevTools version 2.37.1

相关问题