Skip to content

Commit eb8bc23

Browse files
ahmeddhusloic-sharma
authored andcommitted
Add SliverGrid.list convenience constructor (flutter#173925)
This PR adds a new `SliverGrid.list` convenience constructor that accepts a `List<Widget> children` parameter, providing a cleaner API compared to manually creating `SliverChildListDelegate`. ## What was added The constructor uses `SliverChildListDelegate` internally and follows the same pattern as existing convenience constructors like `SliverGrid.count` and `SliverGrid.extent`. This addresses the use case where developers want to create sliver grids with predefined widget lists without the verbosity of manually constructing the delegate. ## Before/After comparison **Before:** ```dart SliverGrid( gridDelegate: gridDelegate, delegate: SliverChildListDelegate([widget1, widget2, widget3]), ) ``` **After:** ```dart SliverGrid.list( gridDelegate: gridDelegate, children: [widget1, widget2, widget3], ) ``` ## Implementation details - Added `SliverGrid.list` constructor in `packages/flutter/lib/src/widgets/sliver.dart` - Constructor accepts `List<Widget> children` and all necessary delegate configuration parameters - Uses `SliverChildListDelegate` internally for consistent behavior - Added comprehensive test coverage in `packages/flutter/test/widgets/slivers_test.dart` ## Issue addressed Fixes: flutter#173018 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. --------- Co-authored-by: Loïc Sharma <737941+loic-sharma@users.noreply.github.com>
1 parent dfa6f0d commit eb8bc23

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed

packages/flutter/lib/src/widgets/sliver.dart

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,60 @@ class SliverGrid extends SliverMultiBoxAdaptorWidget {
803803
),
804804
super(delegate: SliverChildListDelegate(children));
805805

806+
/// Creates a sliver that places multiple box children in a two dimensional
807+
/// arrangement.
808+
///
809+
/// _To learn more about slivers, see [CustomScrollView.slivers]._
810+
///
811+
/// Uses a [SliverChildListDelegate] as the [delegate].
812+
///
813+
/// The `addAutomaticKeepAlives` argument corresponds to the
814+
/// [SliverChildListDelegate.addAutomaticKeepAlives] property. The
815+
/// `addRepaintBoundaries` argument corresponds to the
816+
/// [SliverChildListDelegate.addRepaintBoundaries] property. The
817+
/// `addSemanticIndexes` argument corresponds to the
818+
/// [SliverChildListDelegate.addSemanticIndexes] property. The
819+
/// `semanticIndexOffset` argument corresponds to the
820+
/// [SliverChildListDelegate.semanticIndexOffset] property.
821+
///
822+
/// {@tool snippet}
823+
/// This example, which would be inserted into a [CustomScrollView.slivers]
824+
/// list, shows a grid of [Container] widgets.
825+
///
826+
/// ```dart
827+
/// SliverGrid.list(
828+
/// gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
829+
/// crossAxisCount: 3,
830+
/// ),
831+
/// children: <Widget>[
832+
/// Container(color: Colors.red),
833+
/// Container(color: Colors.green),
834+
/// Container(color: Colors.blue),
835+
/// Container(color: Colors.yellow),
836+
/// Container(color: Colors.orange),
837+
/// Container(color: Colors.purple),
838+
/// ],
839+
/// );
840+
/// ```
841+
/// {@end-tool}
842+
SliverGrid.list({
843+
super.key,
844+
required this.gridDelegate,
845+
required List<Widget> children,
846+
bool addAutomaticKeepAlives = true,
847+
bool addRepaintBoundaries = true,
848+
bool addSemanticIndexes = true,
849+
int semanticIndexOffset = 0,
850+
}) : super(
851+
delegate: SliverChildListDelegate(
852+
children,
853+
addAutomaticKeepAlives: addAutomaticKeepAlives,
854+
addRepaintBoundaries: addRepaintBoundaries,
855+
addSemanticIndexes: addSemanticIndexes,
856+
semanticIndexOffset: semanticIndexOffset,
857+
),
858+
);
859+
806860
/// The delegate that controls the size and position of the children.
807861
final SliverGridDelegate gridDelegate;
808862

packages/flutter/test/widgets/slivers_test.dart

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1389,6 +1389,65 @@ void main() {
13891389
expect(secondTapped, 1);
13901390
});
13911391

1392+
testWidgets('SliverGrid.list can display children', (WidgetTester tester) async {
1393+
int firstTapped = 0;
1394+
int secondTapped = 0;
1395+
final Key key = UniqueKey();
1396+
await tester.pumpWidget(
1397+
MaterialApp(
1398+
home: Scaffold(
1399+
key: key,
1400+
body: CustomScrollView(
1401+
slivers: <Widget>[
1402+
SliverGrid.list(
1403+
gridDelegate: _TestArbitrarySliverGridDelegate(),
1404+
children: <Widget>[
1405+
Material(
1406+
color: Colors.yellow,
1407+
child: InkWell(onTap: () => firstTapped++, child: const Text('First')),
1408+
),
1409+
Material(
1410+
color: Colors.red,
1411+
child: InkWell(onTap: () => secondTapped++, child: const Text('Second')),
1412+
),
1413+
],
1414+
),
1415+
],
1416+
),
1417+
),
1418+
),
1419+
);
1420+
1421+
// Verify correct hit testing
1422+
await tester.tap(find.text('First'));
1423+
expect(firstTapped, 1);
1424+
expect(secondTapped, 0);
1425+
firstTapped = 0;
1426+
await tester.tap(find.text('Second'));
1427+
expect(firstTapped, 0);
1428+
expect(secondTapped, 1);
1429+
});
1430+
1431+
testWidgets('SliverGrid.list with empty children list', (WidgetTester tester) async {
1432+
await tester.pumpWidget(
1433+
MaterialApp(
1434+
home: Scaffold(
1435+
body: CustomScrollView(
1436+
slivers: <Widget>[
1437+
SliverGrid.list(
1438+
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
1439+
children: const <Widget>[],
1440+
),
1441+
],
1442+
),
1443+
),
1444+
),
1445+
);
1446+
1447+
// Should render without errors - the SliverGrid should be present even with empty children
1448+
expect(find.byType(CustomScrollView), findsOneWidget);
1449+
});
1450+
13921451
testWidgets('SliverGridRegularTileLayout.computeMaxScrollOffset handles 0 children', (
13931452
WidgetTester tester,
13941453
) async {

0 commit comments

Comments
 (0)