From cd6ed39550d8794f50cb1bcda2c59b9ceb0d3ccb Mon Sep 17 00:00:00 2001 From: Simone Stasi <62812903+sstasi95@users.noreply.github.com> Date: Thu, 1 Feb 2024 20:07:45 +0100 Subject: [PATCH] fix CupertinoTabView's Android back button handling with PopScope (#141604) This PR fixes CupertinoTabView's handling of Android back button with PopScope and nested navigators by calling `NavigatorState.maybePop` instead of `NavigatorState.pop`, so that the Navigator pops only when it should. Fix #139050 --- .../flutter/lib/src/cupertino/tab_view.dart | 2 +- packages/flutter/test/cupertino/tab_test.dart | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/packages/flutter/lib/src/cupertino/tab_view.dart b/packages/flutter/lib/src/cupertino/tab_view.dart index 1d38eb0bf7..b08bcdda8f 100644 --- a/packages/flutter/lib/src/cupertino/tab_view.dart +++ b/packages/flutter/lib/src/cupertino/tab_view.dart @@ -197,7 +197,7 @@ class _CupertinoTabViewState extends State { if (!_isActive) { return; } - _navigatorKey.currentState!.pop(); + _navigatorKey.currentState!.maybePop(); }, child: child, ); diff --git a/packages/flutter/test/cupertino/tab_test.dart b/packages/flutter/test/cupertino/tab_test.dart index 63001a64f3..d96760fb33 100644 --- a/packages/flutter/test/cupertino/tab_test.dart +++ b/packages/flutter/test/cupertino/tab_test.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'package:flutter/cupertino.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { @@ -289,4 +290,37 @@ void main() { expect(find.text('home'), findsOneWidget); expect(find.text('second route'), findsNothing); }); + + testWidgets('Handles Android back button', (WidgetTester tester) async { + final GlobalKey key = GlobalKey(); + await tester.pumpWidget( + CupertinoApp( + home: CupertinoTabScaffold( + tabBar: CupertinoTabBar( + items: const [ + BottomNavigationBarItem(label: '', icon: Text('1')), + BottomNavigationBarItem(label: '', icon: Text('2')) + ], + ), + tabBuilder: (_, int i) => PopScope( + canPop: false, + child: CupertinoTabView( + navigatorKey: key, + builder: (BuildContext context) => const Text('first route'), + ), + ), + ), + ), + ); + + expect(find.text('first route'), findsOneWidget); + + // Simulate android back button intent. + final ByteData message = const JSONMethodCodec().encodeMethodCall(const MethodCall('popRoute')); + await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) {}); + await tester.pumpAndSettle(); + + // Navigator didn't pop, so first route is still visible + expect(find.text('first route'), findsOneWidget); + }); }