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); + }); }