ShowCaretOnScreen is correctly scheduled within a SliverMainAxisGroup (#141671)

Fixes #141577 
Fixes #135407
This commit is contained in:
yim 2024-02-18 10:28:22 +08:00 committed by GitHub
parent deaf53ef7e
commit 73c26a1c0b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 88 additions and 0 deletions

View file

@ -203,6 +203,30 @@ class RenderSliverMainAxisGroup extends RenderSliver with ContainerRenderObjectM
}
}
@override
double? childScrollOffset(RenderObject child) {
assert(child.parent == this);
final GrowthDirection growthDirection = constraints.growthDirection;
switch (growthDirection) {
case GrowthDirection.forward:
double childScrollOffset = 0.0;
RenderSliver? current = childBefore(child as RenderSliver);
while (current != null) {
childScrollOffset += current.geometry!.scrollExtent;
current = childBefore(current);
}
return childScrollOffset;
case GrowthDirection.reverse:
double childScrollOffset = 0.0;
RenderSliver? current = childAfter(child as RenderSliver);
while (current != null) {
childScrollOffset -= current.geometry!.scrollExtent;
current = childAfter(current);
}
return childScrollOffset;
}
}
@override
double childMainAxisPosition(RenderSliver child) {
switch (constraints.axisDirection) {
@ -254,6 +278,15 @@ class RenderSliverMainAxisGroup extends RenderSliver with ContainerRenderObjectM
offset += childLayoutGeometry.scrollExtent;
maxPaintExtent += child.geometry!.maxPaintExtent;
child = childAfter(child);
assert(() {
if (child != null && maxPaintExtent.isInfinite) {
throw FlutterError(
'Unreachable sliver found, you may have a sliver behind '
'a sliver with infinite extent. '
);
}
return true;
}());
}
final double totalScrollExtent = offset;

View file

@ -17101,6 +17101,44 @@ void main() {
await tester.pumpAndSettle();
expect(notifyCount, equals(1));
});
testWidgets('ShowCaretOnScreen is correctly scheduled within a SliverMainAxisGroup', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
final Widget widget = MaterialApp(
home: Scaffold(
body: CustomScrollView(
controller: scrollController,
slivers: const <Widget>[
SliverMainAxisGroup(
slivers: <Widget>[
SliverToBoxAdapter(
child: SizedBox(
height: 600,
),
),
SliverToBoxAdapter(
child: SizedBox(
height: 44,
child: TextField(),
),
),
SliverToBoxAdapter(
child: SizedBox(
height: 500,
),
),
],
)
],
),
),
);
await tester.pumpWidget(widget);
await tester.showKeyboard(find.byType(EditableText));
await tester.pumpAndSettle();
expect(scrollController.offset, 75.0);
});
}
class UnsettableController extends TextEditingController {

View file

@ -728,6 +728,23 @@ void main() {
) as RenderSliverMainAxisGroup;
expect(renderGroup.geometry!.cacheExtent, 850.0);
});
testWidgets('SliverMainAxisGroup correctly handles ensureVisible', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
await tester.pumpWidget(
_buildSliverMainAxisGroup(
viewportHeight: 300,
slivers: <Widget>[
const SliverToBoxAdapter(child: SizedBox(height: 300)),
SliverToBoxAdapter(child: SizedBox(key: key, height: 100)),
const SliverToBoxAdapter(child: SizedBox(height: 300)),
]
)
);
Scrollable.ensureVisible(key.currentContext!);
await tester.pumpAndSettle();
expect(tester.getTopLeft(find.byKey(key)), Offset.zero);
});
}
Widget _buildSliverList({