Fix SliverPadding dropping the chain on scrollOffsetCorrection propagation (#14789) * Fix SliverPadding dropping the chain on scrollOffsetCorrection propagation * review doc
diff --git a/packages/flutter/lib/src/rendering/sliver.dart b/packages/flutter/lib/src/rendering/sliver.dart index 2806728..0d16be6 100644 --- a/packages/flutter/lib/src/rendering/sliver.dart +++ b/packages/flutter/lib/src/rendering/sliver.dart
@@ -520,6 +520,10 @@ /// If this is non-zero after [RenderSliver.performLayout] returns, the scroll /// offset will be adjusted by the parent and then the entire layout of the /// parent will be rerun. + /// + /// If the parent is also a [RenderSliver], it must propagate this value + /// in its own [RenderSliver.geometry] property until a viewport which adjusts + /// its offset based on this value. final double scrollOffsetCorrection; /// Asserts that this geometry is internally consistent.
diff --git a/packages/flutter/lib/src/rendering/sliver_padding.dart b/packages/flutter/lib/src/rendering/sliver_padding.dart index 21f1ecd..00716b2 100644 --- a/packages/flutter/lib/src/rendering/sliver_padding.dart +++ b/packages/flutter/lib/src/rendering/sliver_padding.dart
@@ -189,6 +189,12 @@ parentUsesSize: true, ); final SliverGeometry childLayoutGeometry = child.geometry; + if (childLayoutGeometry.scrollOffsetCorrection != null) { + geometry = new SliverGeometry( + scrollOffsetCorrection: childLayoutGeometry.scrollOffsetCorrection, + ); + return; + } final double beforePaddingPaintExtent = calculatePaintOffset( constraints, from: 0.0,
diff --git a/packages/flutter/test/widgets/slivers_padding_test.dart b/packages/flutter/test/widgets/slivers_padding_test.dart index 08c640b..e566999 100644 --- a/packages/flutter/test/widgets/slivers_padding_test.dart +++ b/packages/flutter/test/widgets/slivers_padding_test.dart
@@ -357,4 +357,69 @@ ); expect(tester.renderObject<RenderSliverPadding>(find.byType(SliverPadding)).afterPadding, 1.0); }); + + testWidgets('SliverPadding propagates geometry offset corrections', (WidgetTester tester) async { + Widget listBuilder(IndexedWidgetBuilder sliverChildBuilder) { + return new Directionality( + textDirection: TextDirection.ltr, + child: new CustomScrollView( + slivers: <Widget>[ + new SliverPadding( + padding: EdgeInsets.zero, + sliver: new SliverList( + delegate: new SliverChildBuilderDelegate( + sliverChildBuilder, + childCount: 10, + ), + ), + ), + ], + ), + ); + } + + await tester.pumpWidget( + listBuilder( + (BuildContext context, int index) { + return new Container( + height: 200.0, + child: new Center( + child: new Text(index.toString()), + ), + ); + }, + ), + ); + + await tester.drag(find.text('2'), const Offset(0.0, -300.0)); + await tester.pump(); + + expect( + tester.getRect(find.widgetWithText(Container, '2')), + new Rect.fromLTRB(0.0, 100.0, 800.0, 300.0), + ); + + // Now item 0 is 400.0px and going back will underflow. + await tester.pumpWidget( + listBuilder( + (BuildContext context, int index) { + return new Container( + height: index == 0 ? 400.0 : 200.0, + child: new Center( + child: new Text(index.toString()), + ), + ); + }, + ), + ); + + await tester.drag(find.text('2'), const Offset(0.0, 300.0)); + // On this one frame, the scroll correction must properly propagate. + await tester.pump(); + + expect( + tester.getRect(find.widgetWithText(Container, '0')), + new Rect.fromLTRB(0.0, -200.0, 800.0, 200.0), + ); + }); }