Skip to content

Commit cd6ed39

Browse files
authored
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
1 parent 5f9bd7f commit cd6ed39

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

packages/flutter/lib/src/cupertino/tab_view.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ class _CupertinoTabViewState extends State<CupertinoTabView> {
197197
if (!_isActive) {
198198
return;
199199
}
200-
_navigatorKey.currentState!.pop();
200+
_navigatorKey.currentState!.maybePop();
201201
},
202202
child: child,
203203
);

packages/flutter/test/cupertino/tab_test.dart

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// found in the LICENSE file.
44

55
import 'package:flutter/cupertino.dart';
6+
import 'package:flutter/services.dart';
67
import 'package:flutter_test/flutter_test.dart';
78

89
void main() {
@@ -289,4 +290,37 @@ void main() {
289290
expect(find.text('home'), findsOneWidget);
290291
expect(find.text('second route'), findsNothing);
291292
});
293+
294+
testWidgets('Handles Android back button', (WidgetTester tester) async {
295+
final GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
296+
await tester.pumpWidget(
297+
CupertinoApp(
298+
home: CupertinoTabScaffold(
299+
tabBar: CupertinoTabBar(
300+
items: const <BottomNavigationBarItem>[
301+
BottomNavigationBarItem(label: '', icon: Text('1')),
302+
BottomNavigationBarItem(label: '', icon: Text('2'))
303+
],
304+
),
305+
tabBuilder: (_, int i) => PopScope(
306+
canPop: false,
307+
child: CupertinoTabView(
308+
navigatorKey: key,
309+
builder: (BuildContext context) => const Text('first route'),
310+
),
311+
),
312+
),
313+
),
314+
);
315+
316+
expect(find.text('first route'), findsOneWidget);
317+
318+
// Simulate android back button intent.
319+
final ByteData message = const JSONMethodCodec().encodeMethodCall(const MethodCall('popRoute'));
320+
await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) {});
321+
await tester.pumpAndSettle();
322+
323+
// Navigator didn't pop, so first route is still visible
324+
expect(find.text('first route'), findsOneWidget);
325+
});
292326
}

0 commit comments

Comments
 (0)