From d1136e31090ca1191c8f3ffe483931ba083fc5cd Mon Sep 17 00:00:00 2001 From: Sander Kersten Date: Thu, 21 Feb 2019 00:42:15 +0100 Subject: [PATCH] Fix issue where SliverPersistentHeader that is both floating and pinned would scroll down when scrolling past the beginning of the ScrollView (#27433) --- .../rendering/sliver_persistent_header.dart | 1 + .../slivers_appbar_floating_pinned_test.dart | 102 ++++++++++++++++++ 2 files changed, 103 insertions(+) diff --git a/packages/flutter/lib/src/rendering/sliver_persistent_header.dart b/packages/flutter/lib/src/rendering/sliver_persistent_header.dart index a00a684cb4..84a9b0ce2f 100644 --- a/packages/flutter/lib/src/rendering/sliver_persistent_header.dart +++ b/packages/flutter/lib/src/rendering/sliver_persistent_header.dart @@ -524,6 +524,7 @@ abstract class RenderSliverFloatingPinnedPersistentHeader extends RenderSliverFl final double layoutExtent = maxExtent - constraints.scrollOffset; geometry = SliverGeometry( scrollExtent: maxExtent, + paintOrigin: math.min(constraints.overlap, 0.0), paintExtent: clampedPaintExtent, layoutExtent: layoutExtent.clamp(0.0, clampedPaintExtent), maxPaintExtent: maxExtent, diff --git a/packages/flutter/test/widgets/slivers_appbar_floating_pinned_test.dart b/packages/flutter/test/widgets/slivers_appbar_floating_pinned_test.dart index 69614fec7f..563920b561 100644 --- a/packages/flutter/test/widgets/slivers_appbar_floating_pinned_test.dart +++ b/packages/flutter/test/widgets/slivers_appbar_floating_pinned_test.dart @@ -112,4 +112,106 @@ void main() { expect(render.geometry.paintExtent, availableHeight); expect(render.geometry.layoutExtent, 0.0); }); + + testWidgets('Pinned and floating SliverAppBar sticks to top the content is scroll down', (WidgetTester tester) async { + const Key anchor = Key('drag'); + await tester.pumpWidget( + MaterialApp( + home: Center( + child: Container( + height: 300, + color: Colors.green, + child: CustomScrollView( + physics: const BouncingScrollPhysics(), + slivers: [ + const SliverAppBar( + pinned: true, + floating: true, + expandedHeight: 100.0, + ), + SliverToBoxAdapter(child: Container(key: anchor, color: Colors.red, height: 100)), + SliverToBoxAdapter(child: Container(height: 600, color: Colors.green)), + ], + ), + ), + ), + ), + ); + final RenderSliverFloatingPinnedPersistentHeader render = tester.renderObject(find.byType(SliverAppBar)); + + const double scrollDistance = 40; + final TestGesture gesture = await tester.press(find.byKey(anchor)); + await gesture.moveBy(const Offset(0, scrollDistance)); + await tester.pump(); + + expect(render.geometry.paintOrigin, -scrollDistance); + }); + + testWidgets('Floating SliverAppBar sticks to top the content is scroll down', (WidgetTester tester) async { + const Key anchor = Key('drag'); + await tester.pumpWidget( + MaterialApp( + home: Center( + child: Container( + height: 300, + color: Colors.green, + child: CustomScrollView( + physics: const BouncingScrollPhysics(), + slivers: [ + const SliverAppBar( + pinned: false, + floating: true, + expandedHeight: 100.0, + ), + SliverToBoxAdapter(child: Container(key: anchor, color: Colors.red, height: 100)), + SliverToBoxAdapter(child: Container(height: 600, color: Colors.green)), + ], + ), + ), + ), + ), + ); + final RenderSliverFloatingPersistentHeader render = tester.renderObject(find.byType(SliverAppBar)); + + const double scrollDistance = 40; + final TestGesture gesture = await tester.press(find.byKey(anchor)); + await gesture.moveBy(const Offset(0, scrollDistance)); + await tester.pump(); + + expect(render.geometry.paintOrigin, -scrollDistance); + }); + + testWidgets('Pinned SliverAppBar sticks to top the content is scroll down', (WidgetTester tester) async { + const Key anchor = Key('drag'); + await tester.pumpWidget( + MaterialApp( + home: Center( + child: Container( + height: 300, + color: Colors.green, + child: CustomScrollView( + physics: const BouncingScrollPhysics(), + slivers: [ + const SliverAppBar( + pinned: true, + floating: false, + expandedHeight: 100.0, + ), + SliverToBoxAdapter(child: Container(key: anchor, color: Colors.red, height: 100)), + SliverToBoxAdapter(child: Container(height: 600, color: Colors.green)), + ], + ), + ), + ), + ), + ); + final RenderSliverPinnedPersistentHeader render = tester.renderObject(find.byType(SliverAppBar)); + + const double scrollDistance = 40; + final TestGesture gesture = await tester.press(find.byKey(anchor)); + await gesture.moveBy(const Offset(0, scrollDistance)); + await tester.pump(); + + expect(render.geometry.paintOrigin, -scrollDistance); + }); }