diff --git a/packages/flutter/lib/src/cupertino/nav_bar.dart b/packages/flutter/lib/src/cupertino/nav_bar.dart index ba4169aa674..6f214cfb287 100644 --- a/packages/flutter/lib/src/cupertino/nav_bar.dart +++ b/packages/flutter/lib/src/cupertino/nav_bar.dart @@ -541,7 +541,7 @@ class _CupertinoNavigationBarState extends State { /// The [stretch] parameter determines whether the nav bar should stretch to /// fill the over-scroll area. The nav bar can still expand and contract as the /// user scrolls, but it will also stretch when the user over-scrolls if the -/// [stretch] value is `true`. Defaults to `true`. +/// [stretch] value is `true`. Defaults to `false`. /// /// See also: /// @@ -566,7 +566,7 @@ class CupertinoSliverNavigationBar extends StatefulWidget { this.padding, this.transitionBetweenRoutes = true, this.heroTag = _defaultHeroTag, - this.stretch = true, + this.stretch = false, }) : assert(automaticallyImplyLeading != null), assert(automaticallyImplyTitle != null), assert( @@ -658,7 +658,12 @@ class CupertinoSliverNavigationBar extends StatefulWidget { /// /// The nav bar can still expand and contract as the user scrolls, but it will /// also stretch when the user over-scrolls if the [stretch] value is `true`. - /// Defaults to `true`. + /// + /// When set to `true`, the nav bar will prevent subsequent slivers from + /// accessing overscrolls. This may be undesirable for using overscroll-based + /// widgets like the [CupertinoSliverRefreshControl]. + /// + /// Defaults to `false`. final bool stretch; @override diff --git a/packages/flutter/test/cupertino/nav_bar_test.dart b/packages/flutter/test/cupertino/nav_bar_test.dart index 9663b6743b6..34719ef2d03 100644 --- a/packages/flutter/test/cupertino/nav_bar_test.dart +++ b/packages/flutter/test/cupertino/nav_bar_test.dart @@ -1230,6 +1230,7 @@ void main() { const CupertinoSliverNavigationBar( trailing: trailingText, largeTitle: titleText, + stretch: true, ), SliverToBoxAdapter( child: Container( diff --git a/packages/flutter/test/cupertino/refresh_test.dart b/packages/flutter/test/cupertino/refresh_test.dart index e8f818e5b78..b52a3dc7388 100644 --- a/packages/flutter/test/cupertino/refresh_test.dart +++ b/packages/flutter/test/cupertino/refresh_test.dart @@ -918,6 +918,47 @@ void main() { expect(tester.takeException(), isNull); }, variant: const TargetPlatformVariant({ TargetPlatform.iOS, TargetPlatform.macOS })); + + // Test to make sure the refresh sliver's overscroll isn't eaten by the + // nav bar sliver https://github.com/flutter/flutter/issues/74516. + testWidgets( + 'properly displays when the refresh sliver is behind the large title nav bar sliver', + (WidgetTester tester) async { + await tester.pumpWidget( + CupertinoApp( + home: CustomScrollView( + slivers: [ + const CupertinoSliverNavigationBar( + largeTitle: Text('Title'), + ), + CupertinoSliverRefreshControl( + builder: mockHelper.builder, + ), + buildAListOfStuff(), + ], + ), + ), + ); + + final double initialFirstCellY = tester.getTopLeft(find.widgetWithText(Container, '0')).dy; + + // Drag down but not enough to trigger the refresh. + await tester.drag(find.text('0'), const Offset(0.0, 50.0), touchSlopY: 0); + await tester.pump(); + + expect(mockHelper.invocations.first, matchesBuilder( + refreshState: RefreshIndicatorMode.drag, + pulledExtent: 50, + refreshTriggerPullDistance: 100, // default value. + refreshIndicatorExtent: 60, // default value. + )); + expect(mockHelper.invocations, hasLength(1)); + + expect( + tester.getTopLeft(find.widgetWithText(Container, '0')).dy, + initialFirstCellY + 50 + ); + }, variant: const TargetPlatformVariant({ TargetPlatform.iOS, TargetPlatform.macOS })); }; final VoidCallback stateMachineTestGroup = () {