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
This commit is contained in:
Simone Stasi 2024-02-01 20:07:45 +01:00 committed by GitHub
parent 5f9bd7f003
commit cd6ed39550
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 35 additions and 1 deletions

View file

@ -197,7 +197,7 @@ class _CupertinoTabViewState extends State<CupertinoTabView> {
if (!_isActive) {
return;
}
_navigatorKey.currentState!.pop();
_navigatorKey.currentState!.maybePop();
},
child: child,
);

View file

@ -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<NavigatorState> key = GlobalKey<NavigatorState>();
await tester.pumpWidget(
CupertinoApp(
home: CupertinoTabScaffold(
tabBar: CupertinoTabBar(
items: const <BottomNavigationBarItem>[
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);
});
}