Let RenderSliverFixedExtentBoxAdapter handle disappearing top items (#12919)
* fix with first part of test * Test without reshifting * Let sliver fixed extend list also handle disappearing top items.
This commit is contained in:
parent
97b3742f63
commit
152f5258b0
@ -148,6 +148,13 @@ abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAda
|
||||
|
||||
for (int index = indexOf(firstChild) - 1; index >= firstIndex; --index) {
|
||||
final RenderBox child = insertAndLayoutLeadingChild(childConstraints);
|
||||
if (child == null) {
|
||||
// Items before the previously first child are no longer present.
|
||||
// Reset the scroll offset to offset all items prior and up to the
|
||||
// missing item. Let parent re-layout everything.
|
||||
geometry = new SliverGeometry(scrollOffsetCorrection: index * itemExtent);
|
||||
return;
|
||||
}
|
||||
final SliverMultiBoxAdaptorParentData childParentData = child.parentData;
|
||||
childParentData.layoutOffset = indexToLayoutOffset(itemExtent, index);
|
||||
assert(childParentData.index == index);
|
||||
|
@ -194,4 +194,67 @@ void main() {
|
||||
await tester.pumpAndSettle(const Duration(milliseconds: 122));
|
||||
|
||||
});
|
||||
|
||||
testWidgets('Removing offscreen items above and rescrolling does not crash', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(new MaterialApp(
|
||||
home: new CustomScrollView(
|
||||
slivers: <Widget>[
|
||||
new SliverFixedExtentList(
|
||||
itemExtent: 100.0,
|
||||
delegate: new SliverChildBuilderDelegate(
|
||||
(BuildContext context, int index) {
|
||||
return new Container(
|
||||
color: Colors.blue,
|
||||
child: new Text(index.toString()),
|
||||
);
|
||||
},
|
||||
childCount: 30,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
));
|
||||
|
||||
await tester.drag(find.text('5'), const Offset(0.0, -500.0));
|
||||
await tester.pump();
|
||||
|
||||
// Screen is 600px high. Moved bottom item 500px up. It's now at the top.
|
||||
expect(tester.getTopLeft(find.widgetWithText(DecoratedBox, '5')).dy, 0.0);
|
||||
expect(tester.getBottomLeft(find.widgetWithText(DecoratedBox, '10')).dy, 600.0);
|
||||
|
||||
// Stop returning the first 3 items.
|
||||
await tester.pumpWidget(new MaterialApp(
|
||||
home: new CustomScrollView(
|
||||
slivers: <Widget>[
|
||||
new SliverFixedExtentList(
|
||||
itemExtent: 100.0,
|
||||
delegate: new SliverChildBuilderDelegate(
|
||||
(BuildContext context, int index) {
|
||||
if (index > 3) {
|
||||
return new Container(
|
||||
color: Colors.blue,
|
||||
child: new Text(index.toString()),
|
||||
);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
childCount: 30,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
));
|
||||
|
||||
await tester.drag(find.text('5'), const Offset(0.0, 400.0));
|
||||
await tester.pump();
|
||||
|
||||
// Move up by 4 items, meaning item 1 would have been at the top but
|
||||
// 0 through 3 no longer exist, so item 4, 3 items down, is the first one.
|
||||
// Item 4 is also shifted to the top.
|
||||
expect(tester.getTopLeft(find.widgetWithText(DecoratedBox, '4')).dy, 0.0);
|
||||
|
||||
// Because the screen is still 600px, item 9 is now visible at the bottom instead
|
||||
// of what's supposed to be item 6 had we not re-shifted.
|
||||
expect(tester.getBottomLeft(find.widgetWithText(DecoratedBox, '9')).dy, 600.0);
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user