Unverified Commit ff60778c authored by xubaolin's avatar xubaolin Committed by GitHub

[RenderListWheelViewport] Update content dimensions to prevent scroll offset changes (#96102)

parent 099aa029
......@@ -663,12 +663,10 @@ class RenderListWheelViewport
/// by [childManager].
@override
void performLayout() {
final BoxConstraints childConstraints =
constraints.copyWith(
minHeight: _itemExtent,
maxHeight: _itemExtent,
minWidth: 0.0,
);
// Apply the dimensions first in case it changes the scroll offset which
// determines what should be shown.
offset.applyViewportDimension(_viewportExtent);
offset.applyContentDimensions(_minEstimatedScrollExtent, _maxEstimatedScrollExtent);
// The height, in pixel, that children will be visible and might be laid out
// and painted.
......@@ -721,6 +719,11 @@ class RenderListWheelViewport
_destroyChild(firstChild!);
}
final BoxConstraints childConstraints = constraints.copyWith(
minHeight: _itemExtent,
maxHeight: _itemExtent,
minWidth: 0.0,
);
// If there is no child at this stage, we add the first one that is in
// target range.
if (childCount == 0) {
......@@ -759,8 +762,6 @@ class RenderListWheelViewport
_layoutChild(lastChild!, childConstraints, ++currentLastIndex);
}
offset.applyViewportDimension(_viewportExtent);
// Applying content dimensions bases on how the childManager builds widgets:
// if it is available to provide a child just out of target range, then
// we don't know whether there's a limit yet, and set the dimension to the
......
......@@ -766,10 +766,7 @@ class _ListWheelScrollViewState extends State<ListWheelScrollView> {
}
}
@override
Widget build(BuildContext context) {
return NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification notification) {
bool _handleScrollNotification(ScrollNotification notification) {
if (notification.depth == 0
&& widget.onSelectedItemChanged != null
&& notification is ScrollUpdateNotification
......@@ -783,7 +780,12 @@ class _ListWheelScrollViewState extends State<ListWheelScrollView> {
}
}
return false;
},
}
@override
Widget build(BuildContext context) {
return NotificationListener<ScrollNotification>(
onNotification: _handleScrollNotification,
child: _FixedExtentScrollable(
controller: scrollController,
physics: widget.physics,
......
......@@ -230,6 +230,7 @@ void main() {
});
testWidgets('child builder with lower and upper limits', (WidgetTester tester) async {
// Adjust the content dimensions at the end of `RenderListWheelViewport.performLayout()`
final List<int> paintedChildren = <int>[];
final FixedExtentScrollController controller =
......@@ -285,6 +286,69 @@ void main() {
});
group('layout', () {
// Regression test for https://github.com/flutter/flutter/issues/90953
testWidgets('ListWheelScrollView childDelegate update test 2', (WidgetTester tester) async {
final FixedExtentScrollController controller = FixedExtentScrollController( initialItem: 2 );
Widget buildFrame(int childCount) {
return Directionality(
textDirection: TextDirection.ltr,
child: ListWheelScrollView.useDelegate(
controller: controller,
itemExtent: 400.0,
onSelectedItemChanged: (_) { },
childDelegate: ListWheelChildBuilderDelegate(
childCount: childCount,
builder: (BuildContext context, int index) {
return SizedBox(
width: 400.0,
height: 400.0,
child: Text(index.toString()),
);
},
),
),
);
}
await tester.pumpWidget(buildFrame(5));
expect(find.text('0'), findsNothing);
expect(tester.renderObject(find.text('1')).attached, true);
expect(tester.renderObject(find.text('2')).attached, true);
expect(tester.renderObject(find.text('3')).attached, true);
expect(find.text('4'), findsNothing);
// Remove the last 3 items.
await tester.pumpWidget(buildFrame(2));
expect(tester.renderObject(find.text('0')).attached, true);
expect(tester.renderObject(find.text('1')).attached, true);
expect(find.text('3'), findsNothing);
// Add 3 items at the end.
await tester.pumpWidget(buildFrame(5));
expect(tester.renderObject(find.text('0')).attached, true);
expect(tester.renderObject(find.text('1')).attached, true);
expect(tester.renderObject(find.text('2')).attached, true);
expect(find.text('3'), findsNothing);
expect(find.text('4'), findsNothing);
// Scroll to the last item.
final TestGesture scrollGesture = await tester.startGesture(const Offset(10.0, 10.0));
await scrollGesture.moveBy(const Offset(0.0, -1200.0));
await tester.pump();
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsNothing);
expect(find.text('2'), findsNothing);
expect(tester.renderObject(find.text('3')).attached, true);
expect(tester.renderObject(find.text('4')).attached, true);
// Remove the last 3 items.
await tester.pumpWidget(buildFrame(2));
expect(tester.renderObject(find.text('0')).attached, true);
expect(tester.renderObject(find.text('1')).attached, true);
expect(find.text('3'), findsNothing);
});
// Regression test for https://github.com/flutter/flutter/issues/58144
testWidgets('ListWheelScrollView childDelegate update test', (WidgetTester tester) async {
final FixedExtentScrollController controller = FixedExtentScrollController();
......
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