diff --git a/packages/flutter/lib/src/widgets/scroll_view.dart b/packages/flutter/lib/src/widgets/scroll_view.dart index 73107c04dc..6fc5907e0d 100644 --- a/packages/flutter/lib/src/widgets/scroll_view.dart +++ b/packages/flutter/lib/src/widgets/scroll_view.dart @@ -1051,7 +1051,7 @@ class ListView extends BoxScrollView { } return widget; }, - childCount: _computeSemanticChildCount(itemCount), + childCount: _computeActualChildCount(itemCount), addAutomaticKeepAlives: addAutomaticKeepAlives, addRepaintBoundaries: addRepaintBoundaries, addSemanticIndexes: addSemanticIndexes, @@ -1069,7 +1069,7 @@ class ListView extends BoxScrollView { shrinkWrap: shrinkWrap, padding: padding, cacheExtent: cacheExtent, - semanticChildCount: _computeSemanticChildCount(itemCount), + semanticChildCount: itemCount, ); /// Creates a scrollable, linear array of widgets with a custom child model. @@ -1215,8 +1215,8 @@ class ListView extends BoxScrollView { properties.add(DoubleProperty('itemExtent', itemExtent, defaultValue: null)); } - // Helper method to compute the semantic child count for the separated constructor. - static int _computeSemanticChildCount(int itemCount) { + // Helper method to compute the actual child count for the separated constructor. + static int _computeActualChildCount(int itemCount) { return math.max(0, itemCount * 2 - 1); } } diff --git a/packages/flutter/test/widgets/list_view_builder_test.dart b/packages/flutter/test/widgets/list_view_builder_test.dart index 8dae1238be..f0bae19868 100644 --- a/packages/flutter/test/widgets/list_view_builder_test.dart +++ b/packages/flutter/test/widgets/list_view_builder_test.dart @@ -304,6 +304,54 @@ void main() { expect(find.text('s5'), findsNothing); expect(find.text('i6'), findsNothing); }); + + + testWidgets('ListView.separated uses correct semanticChildCount', (WidgetTester tester) async { + Widget buildFrame({int itemCount}) { + return Directionality( + textDirection: TextDirection.ltr, + child: ListView.separated( + itemCount: itemCount, + itemBuilder: (BuildContext context, int index) { + return SizedBox( + height: 100.0, + child: Text('i$index'), + ); + }, + separatorBuilder: (BuildContext context, int index) { + return SizedBox( + height: 10.0, + child: Text('s$index'), + ); + }, + ), + ); + } + + Scrollable scrollable() { + return tester.widget( + find.descendant( + of: find.byType(ListView), + matching: find.byType(Scrollable), + ), + ); + } + + await tester.pumpWidget(buildFrame(itemCount: 0)); + expect(scrollable().semanticChildCount, 0); + + await tester.pumpWidget(buildFrame(itemCount: 1)); + expect(scrollable().semanticChildCount, 1); + + await tester.pumpWidget(buildFrame(itemCount: 2)); + expect(scrollable().semanticChildCount, 2); + + await tester.pumpWidget(buildFrame(itemCount: 3)); + expect(scrollable().semanticChildCount, 3); + + await tester.pumpWidget(buildFrame(itemCount: 4)); + expect(scrollable().semanticChildCount, 4); + }); } void check({ List visible = const [], List hidden = const [] }) {