Skip to content

Commit 1b19858

Browse files
committed
Responsive Grid Creation #2
*Document ResponsiveGrid. *Cleanup unused parameters.
1 parent 93380a3 commit 1b19858

File tree

1 file changed

+52
-15
lines changed

1 file changed

+52
-15
lines changed

lib/responsive_grid.dart

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@ import 'package:flutter/gestures.dart';
22
import 'package:flutter/rendering.dart';
33
import 'package:flutter/widgets.dart';
44

5+
/// A GridView with responsive capabilities.
6+
///
7+
/// ResponsiveGridView extends [GridView] with
8+
/// a custom [ResponsiveGridDelegate] [gridDelegate]
9+
/// that enables greater item size control.
10+
/// Additional parameters [alignment] and [maxRowCount]
11+
/// add grid item positioning capabilities.
512
class ResponsiveGridView extends StatelessWidget {
613
final Axis scrollDirection;
714
final bool reverse;
@@ -10,7 +17,11 @@ class ResponsiveGridView extends StatelessWidget {
1017
final ScrollPhysics physics;
1118
final bool shrinkWrap;
1219
final EdgeInsetsGeometry padding;
20+
21+
/// Align grid items together as a group.
1322
final AlignmentGeometry alignment;
23+
24+
/// A custom [SliverGridDelegate] with item size control.
1425
final ResponsiveGridDelegate gridDelegate;
1526
final IndexedWidgetBuilder itemBuilder;
1627
final int itemCount;
@@ -48,22 +59,31 @@ class ResponsiveGridView extends StatelessWidget {
4859

4960
@override
5061
Widget build(BuildContext context) {
62+
// LayoutBuilder provides constraints required for item sizing calculation.
5163
return LayoutBuilder(builder: (context, constraints) {
64+
// The maximum number of items that can fit on one row.
5265
int crossAxisCount;
66+
// The maximum number of items that fit under the max row count.
5367
int maxItemCount;
68+
// Manual padding adjustment for alignment.
5469
EdgeInsetsGeometry alignmentPadding;
70+
// The width of all items and padding.
5571
double crossAxisWidth;
72+
// The maximum width available for items.
5673
double crossAxisExtent = constraints.maxWidth - padding.horizontal;
5774
assert(crossAxisExtent > 0,
5875
'$padding exceeds layout width (${constraints.maxWidth})');
76+
// Switch between grid delegate behavior.
5977
if (gridDelegate.crossAxisExtent != null) {
78+
// Fixed item size.
6079
crossAxisCount = (crossAxisExtent /
6180
(gridDelegate.crossAxisExtent + gridDelegate.crossAxisSpacing))
6281
.floor();
6382
crossAxisWidth = crossAxisCount *
6483
(gridDelegate.crossAxisExtent + gridDelegate.crossAxisSpacing) +
6584
padding.horizontal;
6685
} else if (gridDelegate.maxCrossAxisExtent != null) {
86+
// Max item size.
6787
crossAxisCount = (crossAxisExtent /
6888
(gridDelegate.maxCrossAxisExtent +
6989
gridDelegate.crossAxisSpacing))
@@ -76,6 +96,7 @@ class ResponsiveGridView extends StatelessWidget {
7696
(childCrossAxisExtent + gridDelegate.crossAxisSpacing) +
7797
padding.horizontal;
7898
} else {
99+
// Min item size.
79100
crossAxisCount = (crossAxisExtent /
80101
(gridDelegate.minCrossAxisExtent +
81102
gridDelegate.crossAxisSpacing))
@@ -88,33 +109,46 @@ class ResponsiveGridView extends StatelessWidget {
88109
(childCrossAxisExtent + gridDelegate.crossAxisSpacing) +
89110
padding.horizontal;
90111
}
112+
// Calculate padding adjustment for alignment.
91113
if (alignment == Alignment.centerLeft ||
92114
alignment == Alignment.topLeft ||
93115
alignment == Alignment.bottomLeft) {
116+
// Align left, no padding.
94117
alignmentPadding = EdgeInsets.only(left: 0);
95118
} else if (alignment == Alignment.center ||
96119
alignment == Alignment.topCenter ||
97120
alignment == Alignment.bottomCenter) {
121+
// Align center, divide remaining space between left and right
122+
// after subtracting last item spacing padding.
98123
double paddingCalc = constraints.maxWidth - crossAxisWidth;
99124
if (paddingCalc <= 0) {
125+
// There is no additional space. No padding.
100126
alignmentPadding = EdgeInsets.only(left: 0);
101127
} else if (paddingCalc > gridDelegate.crossAxisSpacing) {
128+
// There is enough room to center items correctly.
129+
// Add padding equivalent to the last item to the first item.
130+
// Then split the remaining space.
102131
alignmentPadding = EdgeInsets.only(
103132
left: ((constraints.maxWidth -
104133
crossAxisWidth -
105134
gridDelegate.crossAxisSpacing) /
106135
2) +
107136
gridDelegate.crossAxisSpacing);
108137
} else {
138+
// There is not enough space to correctly center items.
139+
// Add all remaining space to left padding.
109140
alignmentPadding = EdgeInsets.only(left: paddingCalc);
110141
}
111142
} else {
143+
// Align right, add all remaining space to left padding.
112144
alignmentPadding =
113145
EdgeInsets.only(left: constraints.maxWidth - crossAxisWidth);
114146
}
147+
// Force row limit by calculating item limit.
115148
if (maxRowCount != null) {
116149
maxItemCount = maxRowCount * crossAxisCount;
117150
}
151+
// Internal children builder delegate.
118152
SliverChildDelegate childrenDelegate = SliverChildBuilderDelegate(
119153
itemBuilder,
120154
childCount: maxItemCount ?? itemCount,
@@ -133,12 +167,7 @@ class ResponsiveGridView extends StatelessWidget {
133167
padding: padding,
134168
gridDelegate: gridDelegate,
135169
childrenDelegate: childrenDelegate,
136-
itemBuilder: itemBuilder,
137170
itemCount: itemCount,
138-
maxRowCount: maxRowCount,
139-
addAutomaticKeepAlives: addAutomaticKeepAlives,
140-
addRepaintBoundaries: addRepaintBoundaries,
141-
addSemanticIndexes: addSemanticIndexes,
142171
cacheExtent: cacheExtent,
143172
semanticChildCount: semanticChildCount,
144173
dragStartBehavior: dragStartBehavior,
@@ -149,15 +178,11 @@ class ResponsiveGridView extends StatelessWidget {
149178
}
150179
}
151180

181+
/// Internal [SliverGridLayout] implementation.
152182
class _ResponsiveGridViewLayout extends BoxScrollView {
153183
final ResponsiveGridDelegate gridDelegate;
154184
final SliverChildDelegate childrenDelegate;
155-
final IndexedWidgetBuilder itemBuilder;
156185
final int itemCount;
157-
final int maxRowCount;
158-
final bool addAutomaticKeepAlives;
159-
final bool addRepaintBoundaries;
160-
final bool addSemanticIndexes;
161186

162187
_ResponsiveGridViewLayout({
163188
Key key,
@@ -170,12 +195,7 @@ class _ResponsiveGridViewLayout extends BoxScrollView {
170195
EdgeInsetsGeometry padding,
171196
@required this.gridDelegate,
172197
@required this.childrenDelegate,
173-
@required this.itemBuilder,
174198
this.itemCount,
175-
this.maxRowCount,
176-
this.addAutomaticKeepAlives = true,
177-
this.addRepaintBoundaries = true,
178-
this.addSemanticIndexes = true,
179199
double cacheExtent,
180200
int semanticChildCount,
181201
DragStartBehavior dragStartBehavior = DragStartBehavior.start,
@@ -206,6 +226,12 @@ class _ResponsiveGridViewLayout extends BoxScrollView {
206226
}
207227
}
208228

229+
/// A [SliverGridDelegate] with item sizing control.
230+
///
231+
/// Set a fixed item size by setting the [crossAxisExtent].
232+
/// Set the maximum item size with [maxCrossAxisExtent].
233+
/// Set the minimum item size with [minCrossAxisExtent].
234+
/// One and only one cross axis extent is required.
209235
class ResponsiveGridDelegate extends SliverGridDelegate {
210236
const ResponsiveGridDelegate({
211237
this.crossAxisExtent,
@@ -223,8 +249,13 @@ class ResponsiveGridDelegate extends SliverGridDelegate {
223249
assert(crossAxisSpacing != null && crossAxisSpacing >= 0),
224250
assert(childAspectRatio != null && childAspectRatio > 0);
225251

252+
/// Fixed item size.
226253
final double crossAxisExtent;
254+
255+
/// Maximum item size.
227256
final double maxCrossAxisExtent;
257+
258+
/// Minimum item size.
228259
final double minCrossAxisExtent;
229260
final double mainAxisSpacing;
230261
final double crossAxisSpacing;
@@ -241,11 +272,17 @@ class ResponsiveGridDelegate extends SliverGridDelegate {
241272
@override
242273
SliverGridLayout getLayout(SliverConstraints constraints) {
243274
assert(_debugAssertIsValid(constraints.crossAxisExtent));
275+
// The maximum number of items that can fit on one row.
244276
int crossAxisCount;
277+
// Item height with padding.
245278
double mainAxisStride;
279+
// Item width with padding.
246280
double crossAxisStride;
281+
// Item height.
247282
double childMainAxisExtent;
283+
// Item width.
248284
double childCrossAxisExtent;
285+
// Switch between item sizing behaviors.
249286
if (this.crossAxisExtent != null) {
250287
crossAxisCount =
251288
(constraints.crossAxisExtent / (crossAxisExtent + crossAxisSpacing))

0 commit comments

Comments
 (0)