diff --git a/packages/flutter/lib/src/material/app_bar.dart b/packages/flutter/lib/src/material/app_bar.dart index b57b7a4960..e2dedcd87c 100644 --- a/packages/flutter/lib/src/material/app_bar.dart +++ b/packages/flutter/lib/src/material/app_bar.dart @@ -709,6 +709,8 @@ class _AppBarState extends State { Scaffold.of(context).openEndDrawer(); } + bool? hadBackButtonWhenRouteWasActive; + @override Widget build(BuildContext context) { assert(!widget.primary || debugCheckHasMediaQuery(context)); @@ -721,7 +723,11 @@ class _AppBarState extends State { final bool hasDrawer = scaffold?.hasDrawer ?? false; final bool hasEndDrawer = scaffold?.hasEndDrawer ?? false; - final bool canPop = parentRoute?.canPop ?? false; + hadBackButtonWhenRouteWasActive ??= false; + if (parentRoute?.isActive == true) { + hadBackButtonWhenRouteWasActive = parentRoute!.canPop; + } + assert(hadBackButtonWhenRouteWasActive != null); final bool useCloseButton = parentRoute is PageRoute && parentRoute.fullscreenDialog; final double toolbarHeight = widget.toolbarHeight ?? kToolbarHeight; @@ -790,7 +796,7 @@ class _AppBarState extends State { tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip, ); } else { - if (!hasEndDrawer && canPop) + if (!hasEndDrawer && hadBackButtonWhenRouteWasActive!) leading = useCloseButton ? const CloseButton() : const BackButton(); } } diff --git a/packages/flutter/lib/src/widgets/routes.dart b/packages/flutter/lib/src/widgets/routes.dart index 3ac19272fe..17ef544e8f 100644 --- a/packages/flutter/lib/src/widgets/routes.dart +++ b/packages/flutter/lib/src/widgets/routes.dart @@ -1460,7 +1460,7 @@ abstract class ModalRoute extends TransitionRoute with LocalHistoryRoute !isFirst || willHandlePopInternally; + bool get canPop => isActive && (!isFirst || willHandlePopInternally); // Internals diff --git a/packages/flutter/test/material/app_bar_test.dart b/packages/flutter/test/material/app_bar_test.dart index af4283c1ce..4ba2602526 100644 --- a/packages/flutter/test/material/app_bar_test.dart +++ b/packages/flutter/test/material/app_bar_test.dart @@ -1122,6 +1122,97 @@ void main() { expect(find.byIcon(Icons.menu), findsNothing); }); + testWidgets('AppBar does not update the leading if a route is popped case 1', (WidgetTester tester) async { + final Page page1 = MaterialPage( + key: const ValueKey('1'), + child: Scaffold( + key: const ValueKey('1'), + appBar: AppBar(), + ) + ); + final Page page2 = MaterialPage( + key: const ValueKey('2'), + child: Scaffold( + key: const ValueKey('2'), + appBar: AppBar(), + ) + ); + List> pages = >[ page1 ]; + await tester.pumpWidget( + MaterialApp( + home: Navigator( + pages: pages, + onPopPage: (Route route, dynamic result) => false, + ), + ), + ); + expect(find.byType(BackButton), findsNothing); + // Update pages + pages = >[ page2 ]; + await tester.pumpWidget( + MaterialApp( + home: Navigator( + pages: pages, + onPopPage: (Route route, dynamic result) => false, + ), + ), + ); + expect(find.byType(BackButton), findsNothing); + }); + + testWidgets('AppBar does not update the leading if a route is popped case 2', (WidgetTester tester) async { + final Page page1 = MaterialPage( + key: const ValueKey('1'), + child: Scaffold( + key: const ValueKey('1'), + appBar: AppBar(), + ) + ); + final Page page2 = MaterialPage( + key: const ValueKey('2'), + child: Scaffold( + key: const ValueKey('2'), + appBar: AppBar(), + ) + ); + List> pages = >[ page1, page2 ]; + await tester.pumpWidget( + MaterialApp( + home: Navigator( + pages: pages, + onPopPage: (Route route, dynamic result) => false, + ), + ), + ); + // The page2 should have a back button + expect( + find.descendant( + of: find.byKey(const ValueKey('2')), + matching: find.byType(BackButton), + ), + findsOneWidget + ); + // Update pages + pages = >[ page1 ]; + await tester.pumpWidget( + MaterialApp( + home: Navigator( + pages: pages, + onPopPage: (Route route, dynamic result) => false, + ), + ), + ); + await tester.pump(const Duration(milliseconds: 10)); + // The back button should persist during the pop animation. + expect( + find.descendant( + of: find.byKey(const ValueKey('2')), + matching: find.byType(BackButton), + ), + findsOneWidget + ); + }); + testWidgets('AppBar ink splash draw on the correct canvas', (WidgetTester tester) async { // This is a regression test for https://github.com/flutter/flutter/issues/58665 final Key key = UniqueKey();