Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[flutter_adaptive_scaffold] Add correct material spacing and panes #7428

Merged
merged 12 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/flutter_adaptive_scaffold/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.2.3

* Update the spacing and margins to the latest material m3 specs.
* Add `margin`, `spacing`, `padding`, `recommendedPanes` and `maxPanes` with their Material value to `Breakpoint`.

## 0.2.2

* Fix a bug where landscape would not show body when using `andUp`.
Expand Down
72 changes: 27 additions & 45 deletions packages/flutter_adaptive_scaffold/lib/src/adaptive_scaffold.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,25 @@ import 'adaptive_layout.dart';
import 'breakpoints.dart';
import 'slot_layout.dart';

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

/// Margin value of the compact breakpoint layout according to the material
/// Spacing value of the medium and up breakpoint according to
/// the material 3 design spec.
const double kMaterialMediumAndUpSpacing = 24;

/// Margin value of the compact breakpoint according to the material
/// design 3 spec.
const double kMaterialCompactMinMargin = 8;
const double kMaterialCompactMargin = 16;

/// Margin value of the medium breakpoint layout according to the material
/// Margin value of the medium breakpoint according to the material
/// design 3 spec.
const double kMaterialMediumMinMargin = 12;
const double kMaterialMediumAndUpMargin = 24;

//// Margin value of the expanded breakpoint layout according to the material
/// Padding value of the compact breakpoint according to the material
/// design 3 spec.
const double kMaterialExpandedMinMargin = 32;
const double kMaterialPadding = 4;

/// Signature for a builder used by [AdaptiveScaffold.navigationRailDestinationBuilder] that converts a
/// [NavigationDestination] to a [NavigationRailDestination].
Expand Down Expand Up @@ -429,40 +433,19 @@ class AdaptiveScaffold extends StatefulWidget {
/// Public helper method to be used for creating a staggered grid following m3
/// specs from a list of [Widget]s
static Builder toMaterialGrid({
List<Widget> thisWidgets = const <Widget>[],
List<Breakpoint> breakpoints = const <Breakpoint>[
Breakpoints.small,
Breakpoints.medium,
Breakpoints.mediumLarge,
Breakpoints.large,
Breakpoints.extraLarge,
],
double margin = 8,
int itemColumns = 1,
required BuildContext context,
List<Widget> widgets = const <Widget>[],
List<Breakpoint> breakpoints = Breakpoints.all,
double? margin,
int? itemColumns,
}) {
return Builder(builder: (BuildContext context) {
Breakpoint? currentBreakpoint;
for (final Breakpoint breakpoint in breakpoints) {
if (breakpoint.isActive(context)) {
currentBreakpoint = breakpoint;
}
}
double? thisMargin = margin;
final Breakpoint? currentBreakpoint =
Breakpoint.activeBreakpointIn(context, breakpoints);
final double thisMargin =
margin ?? currentBreakpoint?.margin ?? kMaterialCompactMargin;
final int thisColumns =
itemColumns ?? currentBreakpoint?.recommendedPanes ?? 1;

if (currentBreakpoint == Breakpoints.small) {
if (thisMargin < kMaterialCompactMinMargin) {
thisMargin = kMaterialCompactMinMargin;
}
} else if (currentBreakpoint == Breakpoints.medium) {
if (thisMargin < kMaterialMediumMinMargin) {
thisMargin = kMaterialMediumMinMargin;
}
} else if (currentBreakpoint == Breakpoints.mediumLarge) {
if (thisMargin < kMaterialExpandedMinMargin) {
thisMargin = kMaterialExpandedMinMargin;
}
}
return CustomScrollView(
primary: false,
controller: ScrollController(),
Expand All @@ -473,11 +456,10 @@ class AdaptiveScaffold extends StatefulWidget {
child: Padding(
padding: EdgeInsets.all(thisMargin),
child: _BrickLayout(
columns: itemColumns,
columnSpacing: kMaterialGutterValue,
itemPadding:
const EdgeInsets.only(bottom: kMaterialGutterValue),
children: thisWidgets,
columns: thisColumns,
columnSpacing: thisMargin,
itemPadding: EdgeInsets.only(bottom: thisMargin),
children: widgets,
),
),
),
Expand Down
60 changes: 55 additions & 5 deletions packages/flutter_adaptive_scaffold/lib/src/breakpoints.dart
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ class Breakpoint {
this.endHeight,
this.andUp = false,
this.platform,
this.spacing = kMaterialMediumAndUpSpacing,
this.margin = kMaterialMediumAndUpMargin,
this.padding = kMaterialPadding,
this.recommendedPanes = 1,
this.maxPanes = 1,
});

/// Returns a [Breakpoint] that can be used as a fallthrough in the
Expand All @@ -148,42 +153,72 @@ class Breakpoint {
endWidth = null,
beginHeight = null,
endHeight = null,
spacing = kMaterialMediumAndUpSpacing,
margin = kMaterialMediumAndUpMargin,
padding = kMaterialPadding,
recommendedPanes = 1,
maxPanes = 1,
andUp = true;

/// Returns a [Breakpoint] with the given constraints for a small screen.
const Breakpoint.small({this.andUp = false, this.platform})
: beginWidth = 0,
endWidth = 600,
beginHeight = null,
endHeight = 480;
endHeight = 480,
spacing = kMaterialCompactSpacing,
margin = kMaterialCompactMargin,
padding = kMaterialPadding,
recommendedPanes = 1,
maxPanes = 1;

/// Returns a [Breakpoint] with the given constraints for a medium screen.
const Breakpoint.medium({this.andUp = false, this.platform})
: beginWidth = 600,
endWidth = 840,
beginHeight = 480,
endHeight = 900;
endHeight = 900,
spacing = kMaterialMediumAndUpSpacing,
margin = kMaterialMediumAndUpMargin,
padding = kMaterialPadding * 2,
recommendedPanes = 1,
maxPanes = 2;

/// Returns a [Breakpoint] with the given constraints for a mediumLarge screen.
const Breakpoint.mediumLarge({this.andUp = false, this.platform})
: beginWidth = 840,
endWidth = 1200,
beginHeight = 900,
endHeight = null;
endHeight = null,
spacing = kMaterialMediumAndUpSpacing,
margin = kMaterialMediumAndUpMargin,
padding = kMaterialPadding * 3,
recommendedPanes = 2,
maxPanes = 2;

/// Returns a [Breakpoint] with the given constraints for a large screen.
const Breakpoint.large({this.andUp = false, this.platform})
: beginWidth = 1200,
endWidth = 1600,
beginHeight = 900,
endHeight = null;
endHeight = null,
spacing = kMaterialMediumAndUpSpacing,
margin = kMaterialMediumAndUpMargin,
padding = kMaterialPadding * 4,
recommendedPanes = 2,
maxPanes = 2;

/// Returns a [Breakpoint] with the given constraints for an extraLarge screen.
const Breakpoint.extraLarge({this.andUp = false, this.platform})
: beginWidth = 1600,
endWidth = null,
beginHeight = 900,
endHeight = null;
endHeight = null,
spacing = kMaterialMediumAndUpSpacing,
margin = kMaterialMediumAndUpMargin,
padding = kMaterialPadding * 5,
recommendedPanes = 2,
maxPanes = 3;

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

/// The default material spacing for the [Breakpoint].
final double spacing;

/// The default material margin for the [Breakpoint].
final double margin;

/// The default material padding for the [Breakpoint].
final double padding;

/// The material recommended number of panes for the [Breakpoint].
final int recommendedPanes;

/// The material maximum number of panes that can be displayed on the [Breakpoint].
final int maxPanes;

/// A method that returns true based on conditions related to the context of
/// the screen such as MediaQuery.sizeOf(context).width, MediaQuery.sizeOf(context).height
/// and MediaQuery.orientationOf(context).
Expand Down
2 changes: 1 addition & 1 deletion packages/flutter_adaptive_scaffold/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: flutter_adaptive_scaffold
description: Widgets to easily build adaptive layouts, including navigation elements.
version: 0.2.2
version: 0.2.3
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+flutter_adaptive_scaffold%22
repository: https://github.com/flutter/packages/tree/main/packages/flutter_adaptive_scaffold

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ void main() {
final Finder primaryNav3 = find.byKey(const Key('primaryNavigation3'));

await tester.binding.setSurfaceSize(SimulatedLayout.small.size);
await tester.pumpWidget(SimulatedLayout.small.app());
await tester.pumpWidget(SimulatedLayout.small.scaffold(tester));
await tester.pumpAndSettle();

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

await tester.binding.setSurfaceSize(SimulatedLayout.medium.size);
await tester.pumpWidget(SimulatedLayout.medium.app());
await tester.pumpWidget(SimulatedLayout.medium.scaffold(tester));
await tester.pumpAndSettle();

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

await tester.binding.setSurfaceSize(SimulatedLayout.mediumLarge.size);
await tester.pumpWidget(SimulatedLayout.mediumLarge.app());
await tester.pumpWidget(SimulatedLayout.mediumLarge.scaffold(tester));
await tester.pumpAndSettle();

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

await tester.binding.setSurfaceSize(SimulatedLayout.large.size);
await tester.pumpWidget(SimulatedLayout.large.app());
await tester.pumpWidget(SimulatedLayout.large.scaffold(tester));
await tester.pumpAndSettle();

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

await tester.binding.setSurfaceSize(SimulatedLayout.extraLarge.size);
await tester.pumpWidget(SimulatedLayout.extraLarge.app());
await tester.pumpWidget(SimulatedLayout.extraLarge.scaffold(tester));
await tester.pumpAndSettle();

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

await tester.binding.setSurfaceSize(SimulatedLayout.small.size);
await tester.pumpWidget(SimulatedLayout.small.app());
await tester.pumpWidget(SimulatedLayout.small.scaffold(tester));
await tester.binding.setSurfaceSize(SimulatedLayout.medium.size);
await tester.pumpWidget(SimulatedLayout.medium.app());
await tester.pumpWidget(SimulatedLayout.medium.scaffold(tester));

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

await tester.binding.setSurfaceSize(SimulatedLayout.small.size);
await tester.pumpWidget(SimulatedLayout.small.app(animations: false));
await tester
.pumpWidget(SimulatedLayout.small.scaffold(tester, animations: false));

await tester.binding.setSurfaceSize(SimulatedLayout.medium.size);
await tester.pumpWidget(SimulatedLayout.medium.app(animations: false));
await tester
.pumpWidget(SimulatedLayout.medium.scaffold(tester, animations: false));

await tester.pump();
await tester.pump(const Duration(milliseconds: 200));
Expand All @@ -179,7 +181,8 @@ void main() {
await Future.forEach(SimulatedLayout.values,
(SimulatedLayout region) async {
int selectedIndex = 0;
final MaterialApp app = region.app(initialIndex: selectedIndex);
final MaterialApp app =
region.scaffold(tester, initialIndex: selectedIndex);
await tester.binding.setSurfaceSize(region.size);
await tester.pumpWidget(app);
await tester.pumpAndSettle();
Expand Down Expand Up @@ -242,7 +245,7 @@ void main() {
(WidgetTester tester) async {
await Future.forEach(SimulatedLayout.values,
(SimulatedLayout region) async {
final MaterialApp app = region.app();
final MaterialApp app = region.scaffold(tester);
await tester.binding.setSurfaceSize(region.size);
await tester.pumpWidget(app);
await tester.pumpAndSettle();
Expand Down Expand Up @@ -272,7 +275,8 @@ void main() {
await Future.forEach(SimulatedLayout.values,
(SimulatedLayout region) async {
int? selectedIndex;
final MaterialApp app = region.app(initialIndex: selectedIndex);
final MaterialApp app =
region.scaffold(tester, initialIndex: selectedIndex);
await tester.binding.setSurfaceSize(region.size);
await tester.pumpWidget(app);
await tester.pumpAndSettle();
Expand Down Expand Up @@ -453,7 +457,7 @@ void main() {
'when view in medium screen, navigation rail must be visible as per theme data values.',
(WidgetTester tester) async {
await tester.binding.setSurfaceSize(SimulatedLayout.medium.size);
await tester.pumpWidget(SimulatedLayout.medium.app());
await tester.pumpWidget(SimulatedLayout.medium.scaffold(tester));
await tester.pumpAndSettle();

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

final Finder primaryNavigationMediumLarge = find.byKey(
Expand Down Expand Up @@ -740,7 +744,7 @@ void main() {
(WidgetTester tester) async {
await tester.binding.setSurfaceSize(SimulatedLayout.medium.size);
await tester.pumpWidget(SimulatedLayout.medium
.app(appBarBreakpoint: AppBarAlwaysOnBreakpoint()));
.scaffold(tester, appBarBreakpoint: AppBarAlwaysOnBreakpoint()));
await tester.pumpAndSettle();

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

await tester.binding.setSurfaceSize(SimulatedLayout.mediumLarge.size);
await tester.pumpWidget(SimulatedLayout.mediumLarge
.app(appBarBreakpoint: AppBarAlwaysOnBreakpoint()));
.scaffold(tester, appBarBreakpoint: AppBarAlwaysOnBreakpoint()));
expect(drawer, findsNothing);
await tester.pumpAndSettle();

Expand Down
Loading