Unverified Commit 924efae9 authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Add visual density to the gallery options (#46090)

This PR adds an option to the gallery options that sets the visual density to one of "standard" (the default), "comfortable", or "compact".
parent ef398d9e
......@@ -64,6 +64,7 @@ class _GalleryAppState extends State<GalleryApp> {
_options = GalleryOptions(
themeMode: ThemeMode.system,
textScaleFactor: kAllGalleryTextScaleValues[0],
visualDensity: kAllGalleryVisualDensityValues[0],
timeDilation: timeDilation,
platform: defaultTargetPlatform,
);
......@@ -140,8 +141,8 @@ class _GalleryAppState extends State<GalleryApp> {
return ScopedModel<AppStateModel>(
model: model,
child: MaterialApp(
theme: kLightGalleryTheme.copyWith(platform: _options.platform),
darkTheme: kDarkGalleryTheme.copyWith(platform: _options.platform),
theme: kLightGalleryTheme.copyWith(platform: _options.platform, visualDensity: _options.visualDensity.visualDensity),
darkTheme: kDarkGalleryTheme.copyWith(platform: _options.platform, visualDensity: _options.visualDensity.visualDensity),
themeMode: _options.themeMode,
title: 'Flutter Gallery',
color: Colors.grey,
......
......@@ -11,6 +11,7 @@ class GalleryOptions {
GalleryOptions({
this.themeMode,
this.textScaleFactor,
this.visualDensity,
this.textDirection = TextDirection.ltr,
this.timeDilation = 1.0,
this.platform,
......@@ -21,6 +22,7 @@ class GalleryOptions {
final ThemeMode themeMode;
final GalleryTextScaleValue textScaleFactor;
final GalleryVisualDensityValue visualDensity;
final TextDirection textDirection;
final double timeDilation;
final TargetPlatform platform;
......@@ -31,6 +33,7 @@ class GalleryOptions {
GalleryOptions copyWith({
ThemeMode themeMode,
GalleryTextScaleValue textScaleFactor,
GalleryVisualDensityValue visualDensity,
TextDirection textDirection,
double timeDilation,
TargetPlatform platform,
......@@ -41,6 +44,7 @@ class GalleryOptions {
return GalleryOptions(
themeMode: themeMode ?? this.themeMode,
textScaleFactor: textScaleFactor ?? this.textScaleFactor,
visualDensity: visualDensity ?? this.visualDensity,
textDirection: textDirection ?? this.textDirection,
timeDilation: timeDilation ?? this.timeDilation,
platform: platform ?? this.platform,
......@@ -57,6 +61,7 @@ class GalleryOptions {
return other is GalleryOptions
&& other.themeMode == themeMode
&& other.textScaleFactor == textScaleFactor
&& other.visualDensity == visualDensity
&& other.textDirection == textDirection
&& other.platform == platform
&& other.showPerformanceOverlay == showPerformanceOverlay
......@@ -68,6 +73,7 @@ class GalleryOptions {
int get hashCode => hashValues(
themeMode,
textScaleFactor,
visualDensity,
textDirection,
timeDilation,
platform,
......@@ -300,6 +306,52 @@ class _TextScaleFactorItem extends StatelessWidget {
}
}
class _VisualDensityItem extends StatelessWidget {
const _VisualDensityItem(this.options, this.onOptionsChanged);
final GalleryOptions options;
final ValueChanged<GalleryOptions> onOptionsChanged;
@override
Widget build(BuildContext context) {
return _OptionsItem(
child: Row(
children: <Widget>[
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const Text('Visual density'),
Text(
'${options.visualDensity.label}',
style: Theme.of(context).primaryTextTheme.body1,
),
],
),
),
PopupMenuButton<GalleryVisualDensityValue>(
padding: const EdgeInsetsDirectional.only(end: 16.0),
icon: const Icon(Icons.arrow_drop_down),
itemBuilder: (BuildContext context) {
return kAllGalleryVisualDensityValues.map<PopupMenuItem<GalleryVisualDensityValue>>((GalleryVisualDensityValue densityValue) {
return PopupMenuItem<GalleryVisualDensityValue>(
value: densityValue,
child: Text(densityValue.label),
);
}).toList();
},
onSelected: (GalleryVisualDensityValue densityValue) {
onOptionsChanged(
options.copyWith(visualDensity: densityValue),
);
},
),
],
),
);
}
}
class _TextDirectionItem extends StatelessWidget {
const _TextDirectionItem(this.options, this.onOptionsChanged);
......@@ -469,6 +521,7 @@ class GalleryOptionsPage extends StatelessWidget {
const _Heading('Display'),
_ThemeModeItem(options, onOptionsChanged),
_TextScaleFactorItem(options, onOptionsChanged),
_VisualDensityItem(options, onOptionsChanged),
_TextDirectionItem(options, onOptionsChanged),
_TimeDilationItem(options, onOptionsChanged),
const Divider(),
......
......@@ -36,3 +36,34 @@ const List<GalleryTextScaleValue> kAllGalleryTextScaleValues = <GalleryTextScale
GalleryTextScaleValue(1.3, 'Large'),
GalleryTextScaleValue(2.0, 'Huge'),
];
class GalleryVisualDensityValue {
const GalleryVisualDensityValue(this.visualDensity, this.label);
final VisualDensity visualDensity;
final String label;
@override
bool operator ==(dynamic other) {
if (runtimeType != other.runtimeType)
return false;
final GalleryVisualDensityValue typedOther = other;
return visualDensity == typedOther.visualDensity && label == typedOther.label;
}
@override
int get hashCode => hashValues(visualDensity, label);
@override
String toString() {
return '$runtimeType($label)';
}
}
const List<GalleryVisualDensityValue> kAllGalleryVisualDensityValues = <GalleryVisualDensityValue>[
GalleryVisualDensityValue(VisualDensity(), 'System Default'),
GalleryVisualDensityValue(VisualDensity.comfortable, 'Comfortable'),
GalleryVisualDensityValue(VisualDensity.compact, 'Compact'),
GalleryVisualDensityValue(VisualDensity(horizontal: -3, vertical: -3), 'Very Compact'),
];
......@@ -54,16 +54,40 @@ void main() {
// Switch back to system theme setting: first menu button, choose 'System Default'
await tester.tap(find.byIcon(Icons.arrow_drop_down).first);
await tester.pumpAndSettle();
await tester.tap(find.text('System Default').at(1));
await tester.tap(find.descendant(
of: find.byWidgetPredicate((Widget widget) => widget.runtimeType.toString() == 'PopupMenuItem<ThemeMode>'),
matching: find.text('System Default')
));
await tester.pumpAndSettle();
app = find.byType(MaterialApp).evaluate().first.widget as MaterialApp;
expect(app.themeMode, ThemeMode.system);
// Verify density settings
expect(app.theme.visualDensity, equals(const VisualDensity()));
// Popup the density menu: third menu button, choose 'Compact'
await tester.tap(find.byIcon(Icons.arrow_drop_down).at(2));
await tester.pumpAndSettle();
await tester.tap(find.text('Compact'));
await tester.pumpAndSettle();
app = find.byType(MaterialApp).evaluate().first.widget;
expect(app.theme.visualDensity, equals(VisualDensity.compact));
await tester.tap(find.byIcon(Icons.arrow_drop_down).at(2));
await tester.pumpAndSettle();
await tester.tap(find.descendant(
of: find.byWidgetPredicate((Widget widget) => widget.runtimeType.toString() == 'PopupMenuItem<GalleryVisualDensityValue>'),
matching: find.text('System Default')
));
await tester.pumpAndSettle();
app = find.byType(MaterialApp).evaluate().first.widget;
expect(app.theme.visualDensity, equals(const VisualDensity()));
// Verify platform settings
expect(app.theme.platform, equals(TargetPlatform.android));
// Popup the platform menu: third menu button, choose 'Cupertino'
await tester.tap(find.byIcon(Icons.arrow_drop_down).at(2));
// Popup the platform menu: fourth menu button, choose 'Cupertino'
await tester.tap(find.byIcon(Icons.arrow_drop_down).at(3));
await tester.pumpAndSettle();
await tester.tap(find.text('Cupertino').at(1));
await tester.pumpAndSettle();
......@@ -85,7 +109,10 @@ void main() {
// Set font scale back to the default.
await tester.tap(find.byIcon(Icons.arrow_drop_down).at(1));
await tester.pumpAndSettle();
await tester.tap(find.text('System Default').at(1));
await tester.tap(find.descendant(
of: find.byWidgetPredicate((Widget widget) => widget.runtimeType.toString() == 'PopupMenuItem<GalleryTextScaleValue>'),
matching: find.text('System Default')
));
await tester.pumpAndSettle();
textSize = tester.getSize(find.text('Text size'));
expect(textSize, origTextSize);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment