Commit 0a8713ef authored by Jason Simmons's avatar Jason Simmons Committed by GitHub

Do not apply scroll offset corrections with zero values during sliver list layout (#10574)

Fixes https://github.com/flutter/flutter/issues/10547
parent 285ab18d
...@@ -485,13 +485,13 @@ class SliverGeometry { ...@@ -485,13 +485,13 @@ class SliverGeometry {
double hitTestExtent, double hitTestExtent,
bool visible, bool visible,
this.hasVisualOverflow: false, this.hasVisualOverflow: false,
this.scrollOffsetCorrection: 0.0 this.scrollOffsetCorrection,
}) : assert(scrollExtent != null), }) : assert(scrollExtent != null),
assert(paintExtent != null), assert(paintExtent != null),
assert(paintOrigin != null), assert(paintOrigin != null),
assert(maxPaintExtent != null), assert(maxPaintExtent != null),
assert(hasVisualOverflow != null), assert(hasVisualOverflow != null),
assert(scrollOffsetCorrection != null), assert(scrollOffsetCorrection != 0.0),
layoutExtent = layoutExtent ?? paintExtent, layoutExtent = layoutExtent ?? paintExtent,
hitTestExtent = hitTestExtent ?? paintExtent, hitTestExtent = hitTestExtent ?? paintExtent,
visible = visible ?? paintExtent > 0.0; visible = visible ?? paintExtent > 0.0;
...@@ -613,7 +613,7 @@ class SliverGeometry { ...@@ -613,7 +613,7 @@ class SliverGeometry {
verify(hitTestExtent >= 0.0, 'The "hitTestExtent" is negative.'); verify(hitTestExtent >= 0.0, 'The "hitTestExtent" is negative.');
verify(visible != null, 'The "visible" property is null.'); verify(visible != null, 'The "visible" property is null.');
verify(hasVisualOverflow != null, 'The "hasVisualOverflow" is null.'); verify(hasVisualOverflow != null, 'The "hasVisualOverflow" is null.');
verify(scrollOffsetCorrection != null, 'The "scrollOffsetCorrection" is null.'); verify(scrollOffsetCorrection != 0.0, 'The "scrollOffsetCorrection" is zero.');
return true; return true;
}); });
return true; return true;
...@@ -648,7 +648,8 @@ class SliverGeometry { ...@@ -648,7 +648,8 @@ class SliverGeometry {
buffer.write('hitTestExtent: ${hitTestExtent.toStringAsFixed(1)}, '); buffer.write('hitTestExtent: ${hitTestExtent.toStringAsFixed(1)}, ');
if (hasVisualOverflow) if (hasVisualOverflow)
buffer.write('hasVisualOverflow: true, '); buffer.write('hasVisualOverflow: true, ');
buffer.write('scrollOffsetCorrection: ${scrollOffsetCorrection.toStringAsFixed(1)}'); if (scrollOffsetCorrection != null)
buffer.write('scrollOffsetCorrection: ${scrollOffsetCorrection.toStringAsFixed(1)}');
buffer.write(')'); buffer.write(')');
return buffer.toString(); return buffer.toString();
} }
......
...@@ -99,15 +99,23 @@ class RenderSliverList extends RenderSliverMultiBoxAdaptor { ...@@ -99,15 +99,23 @@ class RenderSliverList extends RenderSliverMultiBoxAdaptor {
earliestUsefulChild = insertAndLayoutLeadingChild(childConstraints, parentUsesSize: true); earliestUsefulChild = insertAndLayoutLeadingChild(childConstraints, parentUsesSize: true);
if (earliestUsefulChild == null) { if (earliestUsefulChild == null) {
// We ran out of children before reaching the scroll offset.
// We must inform our parent that this sliver cannot fulfill
// its contract and that we need a scroll offset correction.
geometry = new SliverGeometry(
scrollOffsetCorrection: -scrollOffset,
);
final SliverMultiBoxAdaptorParentData childParentData = firstChild.parentData; final SliverMultiBoxAdaptorParentData childParentData = firstChild.parentData;
childParentData.layoutOffset = 0.0; childParentData.layoutOffset = 0.0;
return;
if (scrollOffset == 0.0) {
earliestUsefulChild = firstChild;
leadingChildWithLayout = earliestUsefulChild;
trailingChildWithLayout ??= earliestUsefulChild;
break;
} else {
// We ran out of children before reaching the scroll offset.
// We must inform our parent that this sliver cannot fulfill
// its contract and that we need a scroll offset correction.
geometry = new SliverGeometry(
scrollOffsetCorrection: -scrollOffset,
);
return;
}
} }
final double firstChildScrollOffset = earliestScrollOffset - paintExtentOf(firstChild); final double firstChildScrollOffset = earliestScrollOffset - paintExtentOf(firstChild);
......
...@@ -260,7 +260,7 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix ...@@ -260,7 +260,7 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
assert(childLayoutGeometry.debugAssertIsValid); assert(childLayoutGeometry.debugAssertIsValid);
// If there is a correction to apply, we'll have to start over. // If there is a correction to apply, we'll have to start over.
if (childLayoutGeometry.scrollOffsetCorrection != 0.0) if (childLayoutGeometry.scrollOffsetCorrection != null)
return childLayoutGeometry.scrollOffsetCorrection; return childLayoutGeometry.scrollOffsetCorrection;
// We use the child's paint origin in our coordinate system as the // We use the child's paint origin in our coordinate system as the
......
...@@ -26,7 +26,6 @@ class TestRenderSliverBoxChildManager extends RenderSliverBoxChildManager { ...@@ -26,7 +26,6 @@ class TestRenderSliverBoxChildManager extends RenderSliverBoxChildManager {
@override @override
void createChild(int index, { @required RenderBox after }) { void createChild(int index, { @required RenderBox after }) {
assert(index >= 0);
if (index < 0 || index >= children.length) if (index < 0 || index >= children.length)
return null; return null;
try { try {
...@@ -213,4 +212,36 @@ void main() { ...@@ -213,4 +212,36 @@ void main() {
expect(e.attached, false); expect(e.attached, false);
}); });
test('SliverList - no zero scroll offset correction', () {
RenderSliverList inner;
RenderBox a;
final TestRenderSliverBoxChildManager childManager = new TestRenderSliverBoxChildManager(
children: <RenderBox>[
a = new RenderSizedBox(const Size(100.0, 400.0)),
new RenderSizedBox(const Size(100.0, 400.0)),
new RenderSizedBox(const Size(100.0, 400.0)),
new RenderSizedBox(const Size(100.0, 400.0)),
new RenderSizedBox(const Size(100.0, 400.0)),
],
);
final RenderViewport root = new RenderViewport(
axisDirection: AxisDirection.down,
offset: new ViewportOffset.zero(),
children: <RenderSliver>[
inner = childManager.createRenderObject(),
],
);
layout(root);
final SliverMultiBoxAdaptorParentData parentData = a.parentData;
parentData.layoutOffset = 0.001;
root.offset = new ViewportOffset.fixed(900.0);
pumpFrame();
root.offset = new ViewportOffset.fixed(0.0);
pumpFrame();
expect(inner.geometry.scrollOffsetCorrection, isNull);
});
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment