Skip to content

Commit 73c26a1

Browse files
authored
ShowCaretOnScreen is correctly scheduled within a SliverMainAxisGroup (#141671)
Fixes #141577 Fixes #135407
1 parent deaf53e commit 73c26a1

File tree

3 files changed

+88
-0
lines changed

3 files changed

+88
-0
lines changed

packages/flutter/lib/src/rendering/sliver_group.dart

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,30 @@ class RenderSliverMainAxisGroup extends RenderSliver with ContainerRenderObjectM
203203
}
204204
}
205205

206+
@override
207+
double? childScrollOffset(RenderObject child) {
208+
assert(child.parent == this);
209+
final GrowthDirection growthDirection = constraints.growthDirection;
210+
switch (growthDirection) {
211+
case GrowthDirection.forward:
212+
double childScrollOffset = 0.0;
213+
RenderSliver? current = childBefore(child as RenderSliver);
214+
while (current != null) {
215+
childScrollOffset += current.geometry!.scrollExtent;
216+
current = childBefore(current);
217+
}
218+
return childScrollOffset;
219+
case GrowthDirection.reverse:
220+
double childScrollOffset = 0.0;
221+
RenderSliver? current = childAfter(child as RenderSliver);
222+
while (current != null) {
223+
childScrollOffset -= current.geometry!.scrollExtent;
224+
current = childAfter(current);
225+
}
226+
return childScrollOffset;
227+
}
228+
}
229+
206230
@override
207231
double childMainAxisPosition(RenderSliver child) {
208232
switch (constraints.axisDirection) {
@@ -254,6 +278,15 @@ class RenderSliverMainAxisGroup extends RenderSliver with ContainerRenderObjectM
254278
offset += childLayoutGeometry.scrollExtent;
255279
maxPaintExtent += child.geometry!.maxPaintExtent;
256280
child = childAfter(child);
281+
assert(() {
282+
if (child != null && maxPaintExtent.isInfinite) {
283+
throw FlutterError(
284+
'Unreachable sliver found, you may have a sliver behind '
285+
'a sliver with infinite extent. '
286+
);
287+
}
288+
return true;
289+
}());
257290
}
258291

259292
final double totalScrollExtent = offset;

packages/flutter/test/widgets/editable_text_test.dart

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17101,6 +17101,44 @@ void main() {
1710117101
await tester.pumpAndSettle();
1710217102
expect(notifyCount, equals(1));
1710317103
});
17104+
17105+
testWidgets('ShowCaretOnScreen is correctly scheduled within a SliverMainAxisGroup', (WidgetTester tester) async {
17106+
final ScrollController scrollController = ScrollController();
17107+
addTearDown(scrollController.dispose);
17108+
final Widget widget = MaterialApp(
17109+
home: Scaffold(
17110+
body: CustomScrollView(
17111+
controller: scrollController,
17112+
slivers: const <Widget>[
17113+
SliverMainAxisGroup(
17114+
slivers: <Widget>[
17115+
SliverToBoxAdapter(
17116+
child: SizedBox(
17117+
height: 600,
17118+
),
17119+
),
17120+
SliverToBoxAdapter(
17121+
child: SizedBox(
17122+
height: 44,
17123+
child: TextField(),
17124+
),
17125+
),
17126+
SliverToBoxAdapter(
17127+
child: SizedBox(
17128+
height: 500,
17129+
),
17130+
),
17131+
],
17132+
)
17133+
],
17134+
),
17135+
),
17136+
);
17137+
await tester.pumpWidget(widget);
17138+
await tester.showKeyboard(find.byType(EditableText));
17139+
await tester.pumpAndSettle();
17140+
expect(scrollController.offset, 75.0);
17141+
});
1710417142
}
1710517143

1710617144
class UnsettableController extends TextEditingController {

packages/flutter/test/widgets/sliver_main_axis_group_test.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,23 @@ void main() {
728728
) as RenderSliverMainAxisGroup;
729729
expect(renderGroup.geometry!.cacheExtent, 850.0);
730730
});
731+
732+
testWidgets('SliverMainAxisGroup correctly handles ensureVisible', (WidgetTester tester) async {
733+
final GlobalKey key = GlobalKey();
734+
await tester.pumpWidget(
735+
_buildSliverMainAxisGroup(
736+
viewportHeight: 300,
737+
slivers: <Widget>[
738+
const SliverToBoxAdapter(child: SizedBox(height: 300)),
739+
SliverToBoxAdapter(child: SizedBox(key: key, height: 100)),
740+
const SliverToBoxAdapter(child: SizedBox(height: 300)),
741+
]
742+
)
743+
);
744+
Scrollable.ensureVisible(key.currentContext!);
745+
await tester.pumpAndSettle();
746+
expect(tester.getTopLeft(find.byKey(key)), Offset.zero);
747+
});
731748
}
732749

733750
Widget _buildSliverList({

0 commit comments

Comments
 (0)