diff --git a/packages/flutter/lib/src/material/app_bar.dart b/packages/flutter/lib/src/material/app_bar.dart index 8a30eb6047..a0626f4d72 100644 --- a/packages/flutter/lib/src/material/app_bar.dart +++ b/packages/flutter/lib/src/material/app_bar.dart @@ -823,9 +823,9 @@ class _AppBarState extends State { final bool hasDrawer = scaffold?.hasDrawer ?? false; final bool hasEndDrawer = scaffold?.hasEndDrawer ?? false; - final bool canPop = parentRoute?.canPop ?? false; final bool useCloseButton = parentRoute is PageRoute && parentRoute.fullscreenDialog; - + final bool requiresAppBarDismiss = scaffold?.requiresAppBarDismiss ?? false; + final bool hasActiveRouteBelow = parentRoute?.hasActiveRouteBelow ?? false; final double toolbarHeight = widget.toolbarHeight ?? appBarTheme.toolbarHeight ?? kToolbarHeight; final bool backwardsCompatibility = widget.backwardsCompatibility ?? appBarTheme.backwardsCompatibility ?? false; @@ -896,7 +896,7 @@ class _AppBarState extends State { tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip, ); } else { - if (!hasEndDrawer && canPop) + if (hasActiveRouteBelow || requiresAppBarDismiss) leading = useCloseButton ? const CloseButton() : const BackButton(); } } diff --git a/packages/flutter/lib/src/material/scaffold.dart b/packages/flutter/lib/src/material/scaffold.dart index f851804564..33c9577b55 100644 --- a/packages/flutter/lib/src/material/scaffold.dart +++ b/packages/flutter/lib/src/material/scaffold.dart @@ -1917,13 +1917,20 @@ class ScaffoldState extends State with TickerProviderStateMixin, Resto /// Whether this scaffold has a non-null [Scaffold.appBar]. bool get hasAppBar => widget.appBar != null; + /// Whether this scaffold has a non-null [Scaffold.drawer]. bool get hasDrawer => widget.drawer != null; + /// Whether this scaffold has a non-null [Scaffold.endDrawer]. bool get hasEndDrawer => widget.endDrawer != null; + /// Whether this scaffold has a non-null [Scaffold.floatingActionButton]. bool get hasFloatingActionButton => widget.floatingActionButton != null; + /// Whether this scaffold requires [Scaffold.appBar] to automatically add + /// dismiss button. + bool get requiresAppBarDismiss => _persistentSheetHistoryEntry != null; + double? _appBarMaxHeight; /// The max height the [Scaffold.appBar] uses. /// @@ -2051,28 +2058,28 @@ class ScaffoldState extends State with TickerProviderStateMixin, Resto PersistentBottomSheetController? _currentBottomSheet; final GlobalKey _currentBottomSheetKey = GlobalKey(); + LocalHistoryEntry? _persistentSheetHistoryEntry; void _maybeBuildPersistentBottomSheet() { if (widget.bottomSheet != null && _currentBottomSheet == null) { // The new _currentBottomSheet is not a local history entry so a "back" button // will not be added to the Scaffold's appbar and the bottom sheet will not // support drag or swipe to dismiss. final AnimationController animationController = BottomSheet.createAnimationController(this)..value = 1.0; - LocalHistoryEntry? persistentSheetHistoryEntry; bool _persistentBottomSheetExtentChanged(DraggableScrollableNotification notification) { if (notification.extent > notification.initialExtent) { - if (persistentSheetHistoryEntry == null) { - persistentSheetHistoryEntry = LocalHistoryEntry(onRemove: () { + if (_persistentSheetHistoryEntry == null) { + _persistentSheetHistoryEntry = LocalHistoryEntry(onRemove: () { if (notification.extent > notification.initialExtent) { DraggableScrollableActuator.reset(notification.context); } showBodyScrim(false, 0.0); _floatingActionButtonVisibilityValue = 1.0; - persistentSheetHistoryEntry = null; + _persistentSheetHistoryEntry = null; }); - ModalRoute.of(context)!.addLocalHistoryEntry(persistentSheetHistoryEntry!); + ModalRoute.of(context)!.addLocalHistoryEntry(_persistentSheetHistoryEntry!); } - } else if (persistentSheetHistoryEntry != null) { - ModalRoute.of(context)!.removeLocalHistoryEntry(persistentSheetHistoryEntry!); + } else if (_persistentSheetHistoryEntry != null) { + ModalRoute.of(context)!.removeLocalHistoryEntry(_persistentSheetHistoryEntry!); } return false; } diff --git a/packages/flutter/lib/src/widgets/navigator.dart b/packages/flutter/lib/src/widgets/navigator.dart index 93d0bc5f21..0b92115c15 100644 --- a/packages/flutter/lib/src/widgets/navigator.dart +++ b/packages/flutter/lib/src/widgets/navigator.dart @@ -486,7 +486,6 @@ abstract class Route { } /// Whether there is at least one active route underneath this route. - @protected bool get hasActiveRouteBelow { if (_navigator == null) return false; diff --git a/packages/flutter/test/material/app_bar_test.dart b/packages/flutter/test/material/app_bar_test.dart index 397181f808..c4d2cf0a8e 100644 --- a/packages/flutter/test/material/app_bar_test.dart +++ b/packages/flutter/test/material/app_bar_test.dart @@ -2873,6 +2873,44 @@ void main() { expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); }); + // Regression test for https://github.com/flutter/flutter/issues/80256 + testWidgets('The second page should have a back button even it has a end drawer', (WidgetTester tester) async { + final Page page1 = MaterialPage( + key: const ValueKey('1'), + child: Scaffold( + key: const ValueKey('1'), + appBar: AppBar(), + endDrawer: const Drawer(), + ) + ); + final Page page2 = MaterialPage( + key: const ValueKey('2'), + child: Scaffold( + key: const ValueKey('2'), + appBar: AppBar(), + endDrawer: const Drawer(), + ) + ); + final List> pages = >[ page1, page2 ]; + await tester.pumpWidget( + MaterialApp( + home: Navigator( + pages: pages, + onPopPage: (Route route, Object? result) => false, + ), + ), + ); + + // The page2 should have a back button. + expect( + find.descendant( + of: find.byKey(const ValueKey('2')), + matching: find.byType(BackButton), + ), + findsOneWidget + ); + }); + testWidgets('backgroundColor with FlexibleSpace - reverse', (WidgetTester tester) async { await tester.pumpWidget( _buildAppBar(