Skip to content

Commit c765f57

Browse files
authored
[flutter_adaptive_scaffold] Add correct material spacing and panes (flutter#7428)
*Replace this paragraph with a description of what this PR is changing or adding, and why. Consider including before/after screenshots.* https://m3.material.io/foundations/layout/understanding-layout/parts-of-layout https://m3.material.io/foundations/layout/understanding-layout/spacing *List which issues are fixed by this PR. You must list at least one issue.*
1 parent de42d8e commit c765f57

7 files changed

Lines changed: 414 additions & 80 deletions

File tree

packages/flutter_adaptive_scaffold/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 0.2.3
2+
3+
* Update the spacing and margins to the latest material m3 specs.
4+
* Add `margin`, `spacing`, `padding`, `recommendedPanes` and `maxPanes` with their Material value to `Breakpoint`.
5+
16
## 0.2.2
27

38
* Fix a bug where landscape would not show body when using `andUp`.

packages/flutter_adaptive_scaffold/lib/src/adaptive_scaffold.dart

Lines changed: 27 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,25 @@ import 'adaptive_layout.dart';
88
import 'breakpoints.dart';
99
import 'slot_layout.dart';
1010

11-
/// Gutter value between different parts of the body slot depending on
12-
/// material 3 design spec.
13-
const double kMaterialGutterValue = 8;
11+
/// Spacing value of the compact breakpoint according to
12+
/// the material 3 design spec.
13+
const double kMaterialCompactSpacing = 0;
1414

15-
/// Margin value of the compact breakpoint layout according to the material
15+
/// Spacing value of the medium and up breakpoint according to
16+
/// the material 3 design spec.
17+
const double kMaterialMediumAndUpSpacing = 24;
18+
19+
/// Margin value of the compact breakpoint according to the material
1620
/// design 3 spec.
17-
const double kMaterialCompactMinMargin = 8;
21+
const double kMaterialCompactMargin = 16;
1822

19-
/// Margin value of the medium breakpoint layout according to the material
23+
/// Margin value of the medium breakpoint according to the material
2024
/// design 3 spec.
21-
const double kMaterialMediumMinMargin = 12;
25+
const double kMaterialMediumAndUpMargin = 24;
2226

23-
//// Margin value of the expanded breakpoint layout according to the material
27+
/// Padding value of the compact breakpoint according to the material
2428
/// design 3 spec.
25-
const double kMaterialExpandedMinMargin = 32;
29+
const double kMaterialPadding = 4;
2630

2731
/// Signature for a builder used by [AdaptiveScaffold.navigationRailDestinationBuilder] that converts a
2832
/// [NavigationDestination] to a [NavigationRailDestination].
@@ -429,40 +433,19 @@ class AdaptiveScaffold extends StatefulWidget {
429433
/// Public helper method to be used for creating a staggered grid following m3
430434
/// specs from a list of [Widget]s
431435
static Builder toMaterialGrid({
432-
List<Widget> thisWidgets = const <Widget>[],
433-
List<Breakpoint> breakpoints = const <Breakpoint>[
434-
Breakpoints.small,
435-
Breakpoints.medium,
436-
Breakpoints.mediumLarge,
437-
Breakpoints.large,
438-
Breakpoints.extraLarge,
439-
],
440-
double margin = 8,
441-
int itemColumns = 1,
442-
required BuildContext context,
436+
List<Widget> widgets = const <Widget>[],
437+
List<Breakpoint> breakpoints = Breakpoints.all,
438+
double? margin,
439+
int? itemColumns,
443440
}) {
444441
return Builder(builder: (BuildContext context) {
445-
Breakpoint? currentBreakpoint;
446-
for (final Breakpoint breakpoint in breakpoints) {
447-
if (breakpoint.isActive(context)) {
448-
currentBreakpoint = breakpoint;
449-
}
450-
}
451-
double? thisMargin = margin;
442+
final Breakpoint? currentBreakpoint =
443+
Breakpoint.activeBreakpointIn(context, breakpoints);
444+
final double thisMargin =
445+
margin ?? currentBreakpoint?.margin ?? kMaterialCompactMargin;
446+
final int thisColumns =
447+
itemColumns ?? currentBreakpoint?.recommendedPanes ?? 1;
452448

453-
if (currentBreakpoint == Breakpoints.small) {
454-
if (thisMargin < kMaterialCompactMinMargin) {
455-
thisMargin = kMaterialCompactMinMargin;
456-
}
457-
} else if (currentBreakpoint == Breakpoints.medium) {
458-
if (thisMargin < kMaterialMediumMinMargin) {
459-
thisMargin = kMaterialMediumMinMargin;
460-
}
461-
} else if (currentBreakpoint == Breakpoints.mediumLarge) {
462-
if (thisMargin < kMaterialExpandedMinMargin) {
463-
thisMargin = kMaterialExpandedMinMargin;
464-
}
465-
}
466449
return CustomScrollView(
467450
primary: false,
468451
controller: ScrollController(),
@@ -473,11 +456,10 @@ class AdaptiveScaffold extends StatefulWidget {
473456
child: Padding(
474457
padding: EdgeInsets.all(thisMargin),
475458
child: _BrickLayout(
476-
columns: itemColumns,
477-
columnSpacing: kMaterialGutterValue,
478-
itemPadding:
479-
const EdgeInsets.only(bottom: kMaterialGutterValue),
480-
children: thisWidgets,
459+
columns: thisColumns,
460+
columnSpacing: thisMargin,
461+
itemPadding: EdgeInsets.only(bottom: thisMargin),
462+
children: widgets,
481463
),
482464
),
483465
),

packages/flutter_adaptive_scaffold/lib/src/breakpoints.dart

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ class Breakpoint {
139139
this.endHeight,
140140
this.andUp = false,
141141
this.platform,
142+
this.spacing = kMaterialMediumAndUpSpacing,
143+
this.margin = kMaterialMediumAndUpMargin,
144+
this.padding = kMaterialPadding,
145+
this.recommendedPanes = 1,
146+
this.maxPanes = 1,
142147
});
143148

144149
/// Returns a [Breakpoint] that can be used as a fallthrough in the
@@ -148,42 +153,72 @@ class Breakpoint {
148153
endWidth = null,
149154
beginHeight = null,
150155
endHeight = null,
156+
spacing = kMaterialMediumAndUpSpacing,
157+
margin = kMaterialMediumAndUpMargin,
158+
padding = kMaterialPadding,
159+
recommendedPanes = 1,
160+
maxPanes = 1,
151161
andUp = true;
152162

153163
/// Returns a [Breakpoint] with the given constraints for a small screen.
154164
const Breakpoint.small({this.andUp = false, this.platform})
155165
: beginWidth = 0,
156166
endWidth = 600,
157167
beginHeight = null,
158-
endHeight = 480;
168+
endHeight = 480,
169+
spacing = kMaterialCompactSpacing,
170+
margin = kMaterialCompactMargin,
171+
padding = kMaterialPadding,
172+
recommendedPanes = 1,
173+
maxPanes = 1;
159174

160175
/// Returns a [Breakpoint] with the given constraints for a medium screen.
161176
const Breakpoint.medium({this.andUp = false, this.platform})
162177
: beginWidth = 600,
163178
endWidth = 840,
164179
beginHeight = 480,
165-
endHeight = 900;
180+
endHeight = 900,
181+
spacing = kMaterialMediumAndUpSpacing,
182+
margin = kMaterialMediumAndUpMargin,
183+
padding = kMaterialPadding * 2,
184+
recommendedPanes = 1,
185+
maxPanes = 2;
166186

167187
/// Returns a [Breakpoint] with the given constraints for a mediumLarge screen.
168188
const Breakpoint.mediumLarge({this.andUp = false, this.platform})
169189
: beginWidth = 840,
170190
endWidth = 1200,
171191
beginHeight = 900,
172-
endHeight = null;
192+
endHeight = null,
193+
spacing = kMaterialMediumAndUpSpacing,
194+
margin = kMaterialMediumAndUpMargin,
195+
padding = kMaterialPadding * 3,
196+
recommendedPanes = 2,
197+
maxPanes = 2;
173198

174199
/// Returns a [Breakpoint] with the given constraints for a large screen.
175200
const Breakpoint.large({this.andUp = false, this.platform})
176201
: beginWidth = 1200,
177202
endWidth = 1600,
178203
beginHeight = 900,
179-
endHeight = null;
204+
endHeight = null,
205+
spacing = kMaterialMediumAndUpSpacing,
206+
margin = kMaterialMediumAndUpMargin,
207+
padding = kMaterialPadding * 4,
208+
recommendedPanes = 2,
209+
maxPanes = 2;
180210

181211
/// Returns a [Breakpoint] with the given constraints for an extraLarge screen.
182212
const Breakpoint.extraLarge({this.andUp = false, this.platform})
183213
: beginWidth = 1600,
184214
endWidth = null,
185215
beginHeight = 900,
186-
endHeight = null;
216+
endHeight = null,
217+
spacing = kMaterialMediumAndUpSpacing,
218+
margin = kMaterialMediumAndUpMargin,
219+
padding = kMaterialPadding * 5,
220+
recommendedPanes = 2,
221+
maxPanes = 3;
187222

188223
/// A set of [TargetPlatform]s that the [Breakpoint] will be active on desktop.
189224
static const Set<TargetPlatform> desktop = <TargetPlatform>{
@@ -222,6 +257,21 @@ class Breakpoint {
222257
/// left null then it will be active on all platforms.
223258
final Set<TargetPlatform>? platform;
224259

260+
/// The default material spacing for the [Breakpoint].
261+
final double spacing;
262+
263+
/// The default material margin for the [Breakpoint].
264+
final double margin;
265+
266+
/// The default material padding for the [Breakpoint].
267+
final double padding;
268+
269+
/// The material recommended number of panes for the [Breakpoint].
270+
final int recommendedPanes;
271+
272+
/// The material maximum number of panes that can be displayed on the [Breakpoint].
273+
final int maxPanes;
274+
225275
/// A method that returns true based on conditions related to the context of
226276
/// the screen such as MediaQuery.sizeOf(context).width, MediaQuery.sizeOf(context).height
227277
/// and MediaQuery.orientationOf(context).

packages/flutter_adaptive_scaffold/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: flutter_adaptive_scaffold
22
description: Widgets to easily build adaptive layouts, including navigation elements.
3-
version: 0.2.2
3+
version: 0.2.3
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+flutter_adaptive_scaffold%22
55
repository: https://github.com/flutter/packages/tree/main/packages/flutter_adaptive_scaffold
66

packages/flutter_adaptive_scaffold/test/adaptive_scaffold_test.dart

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ void main() {
3131
final Finder primaryNav3 = find.byKey(const Key('primaryNavigation3'));
3232

3333
await tester.binding.setSurfaceSize(SimulatedLayout.small.size);
34-
await tester.pumpWidget(SimulatedLayout.small.app());
34+
await tester.pumpWidget(SimulatedLayout.small.scaffold(tester));
3535
await tester.pumpAndSettle();
3636

3737
expect(smallBody, findsOneWidget);
@@ -44,7 +44,7 @@ void main() {
4444
expect(tester.getTopLeft(bottomNav), const Offset(0, 1920));
4545

4646
await tester.binding.setSurfaceSize(SimulatedLayout.medium.size);
47-
await tester.pumpWidget(SimulatedLayout.medium.app());
47+
await tester.pumpWidget(SimulatedLayout.medium.scaffold(tester));
4848
await tester.pumpAndSettle();
4949

5050
expect(smallBody, findsNothing);
@@ -60,7 +60,7 @@ void main() {
6060
expect(tester.getBottomRight(primaryNav), const Offset(88, 2000));
6161

6262
await tester.binding.setSurfaceSize(SimulatedLayout.mediumLarge.size);
63-
await tester.pumpWidget(SimulatedLayout.mediumLarge.app());
63+
await tester.pumpWidget(SimulatedLayout.mediumLarge.scaffold(tester));
6464
await tester.pumpAndSettle();
6565

6666
expect(body, findsNothing);
@@ -76,7 +76,7 @@ void main() {
7676
expect(tester.getBottomRight(primaryNav1), const Offset(208, 2000));
7777

7878
await tester.binding.setSurfaceSize(SimulatedLayout.large.size);
79-
await tester.pumpWidget(SimulatedLayout.large.app());
79+
await tester.pumpWidget(SimulatedLayout.large.scaffold(tester));
8080
await tester.pumpAndSettle();
8181

8282
expect(mediumLargeBody, findsNothing);
@@ -92,7 +92,7 @@ void main() {
9292
expect(tester.getBottomRight(primaryNav2), const Offset(208, 2000));
9393

9494
await tester.binding.setSurfaceSize(SimulatedLayout.extraLarge.size);
95-
await tester.pumpWidget(SimulatedLayout.extraLarge.app());
95+
await tester.pumpWidget(SimulatedLayout.extraLarge.scaffold(tester));
9696
await tester.pumpAndSettle();
9797

9898
expect(largeBody, findsNothing);
@@ -114,9 +114,9 @@ void main() {
114114
final Finder sBody = find.byKey(const Key('sBody'));
115115

116116
await tester.binding.setSurfaceSize(SimulatedLayout.small.size);
117-
await tester.pumpWidget(SimulatedLayout.small.app());
117+
await tester.pumpWidget(SimulatedLayout.small.scaffold(tester));
118118
await tester.binding.setSurfaceSize(SimulatedLayout.medium.size);
119-
await tester.pumpWidget(SimulatedLayout.medium.app());
119+
await tester.pumpWidget(SimulatedLayout.medium.scaffold(tester));
120120

121121
await tester.pump();
122122
await tester.pump(const Duration(milliseconds: 200));
@@ -155,10 +155,12 @@ void main() {
155155
final Finder sBody = find.byKey(const Key('sBody'));
156156

157157
await tester.binding.setSurfaceSize(SimulatedLayout.small.size);
158-
await tester.pumpWidget(SimulatedLayout.small.app(animations: false));
158+
await tester
159+
.pumpWidget(SimulatedLayout.small.scaffold(tester, animations: false));
159160

160161
await tester.binding.setSurfaceSize(SimulatedLayout.medium.size);
161-
await tester.pumpWidget(SimulatedLayout.medium.app(animations: false));
162+
await tester
163+
.pumpWidget(SimulatedLayout.medium.scaffold(tester, animations: false));
162164

163165
await tester.pump();
164166
await tester.pump(const Duration(milliseconds: 200));
@@ -179,7 +181,8 @@ void main() {
179181
await Future.forEach(SimulatedLayout.values,
180182
(SimulatedLayout region) async {
181183
int selectedIndex = 0;
182-
final MaterialApp app = region.app(initialIndex: selectedIndex);
184+
final MaterialApp app =
185+
region.scaffold(tester, initialIndex: selectedIndex);
183186
await tester.binding.setSurfaceSize(region.size);
184187
await tester.pumpWidget(app);
185188
await tester.pumpAndSettle();
@@ -242,7 +245,7 @@ void main() {
242245
(WidgetTester tester) async {
243246
await Future.forEach(SimulatedLayout.values,
244247
(SimulatedLayout region) async {
245-
final MaterialApp app = region.app();
248+
final MaterialApp app = region.scaffold(tester);
246249
await tester.binding.setSurfaceSize(region.size);
247250
await tester.pumpWidget(app);
248251
await tester.pumpAndSettle();
@@ -272,7 +275,8 @@ void main() {
272275
await Future.forEach(SimulatedLayout.values,
273276
(SimulatedLayout region) async {
274277
int? selectedIndex;
275-
final MaterialApp app = region.app(initialIndex: selectedIndex);
278+
final MaterialApp app =
279+
region.scaffold(tester, initialIndex: selectedIndex);
276280
await tester.binding.setSurfaceSize(region.size);
277281
await tester.pumpWidget(app);
278282
await tester.pumpAndSettle();
@@ -453,7 +457,7 @@ void main() {
453457
'when view in medium screen, navigation rail must be visible as per theme data values.',
454458
(WidgetTester tester) async {
455459
await tester.binding.setSurfaceSize(SimulatedLayout.medium.size);
456-
await tester.pumpWidget(SimulatedLayout.medium.app());
460+
await tester.pumpWidget(SimulatedLayout.medium.scaffold(tester));
457461
await tester.pumpAndSettle();
458462

459463
final Finder primaryNavigationMedium = find.byKey(
@@ -499,7 +503,7 @@ void main() {
499503
'when view in mediumLarge screen, navigation rail must be visible as per theme data values.',
500504
(WidgetTester tester) async {
501505
await tester.binding.setSurfaceSize(SimulatedLayout.mediumLarge.size);
502-
await tester.pumpWidget(SimulatedLayout.mediumLarge.app());
506+
await tester.pumpWidget(SimulatedLayout.mediumLarge.scaffold(tester));
503507
await tester.pumpAndSettle();
504508

505509
final Finder primaryNavigationMediumLarge = find.byKey(
@@ -740,7 +744,7 @@ void main() {
740744
(WidgetTester tester) async {
741745
await tester.binding.setSurfaceSize(SimulatedLayout.medium.size);
742746
await tester.pumpWidget(SimulatedLayout.medium
743-
.app(appBarBreakpoint: AppBarAlwaysOnBreakpoint()));
747+
.scaffold(tester, appBarBreakpoint: AppBarAlwaysOnBreakpoint()));
744748
await tester.pumpAndSettle();
745749

746750
final Finder appBar = find.byType(AppBar);
@@ -750,7 +754,7 @@ void main() {
750754

751755
await tester.binding.setSurfaceSize(SimulatedLayout.mediumLarge.size);
752756
await tester.pumpWidget(SimulatedLayout.mediumLarge
753-
.app(appBarBreakpoint: AppBarAlwaysOnBreakpoint()));
757+
.scaffold(tester, appBarBreakpoint: AppBarAlwaysOnBreakpoint()));
754758
expect(drawer, findsNothing);
755759
await tester.pumpAndSettle();
756760

0 commit comments

Comments
 (0)