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> { ...@@ -64,6 +64,7 @@ class _GalleryAppState extends State<GalleryApp> {
_options = GalleryOptions( _options = GalleryOptions(
themeMode: ThemeMode.system, themeMode: ThemeMode.system,
textScaleFactor: kAllGalleryTextScaleValues[0], textScaleFactor: kAllGalleryTextScaleValues[0],
visualDensity: kAllGalleryVisualDensityValues[0],
timeDilation: timeDilation, timeDilation: timeDilation,
platform: defaultTargetPlatform, platform: defaultTargetPlatform,
); );
...@@ -140,8 +141,8 @@ class _GalleryAppState extends State<GalleryApp> { ...@@ -140,8 +141,8 @@ class _GalleryAppState extends State<GalleryApp> {
return ScopedModel<AppStateModel>( return ScopedModel<AppStateModel>(
model: model, model: model,
child: MaterialApp( child: MaterialApp(
theme: kLightGalleryTheme.copyWith(platform: _options.platform), theme: kLightGalleryTheme.copyWith(platform: _options.platform, visualDensity: _options.visualDensity.visualDensity),
darkTheme: kDarkGalleryTheme.copyWith(platform: _options.platform), darkTheme: kDarkGalleryTheme.copyWith(platform: _options.platform, visualDensity: _options.visualDensity.visualDensity),
themeMode: _options.themeMode, themeMode: _options.themeMode,
title: 'Flutter Gallery', title: 'Flutter Gallery',
color: Colors.grey, color: Colors.grey,
......
...@@ -11,6 +11,7 @@ class GalleryOptions { ...@@ -11,6 +11,7 @@ class GalleryOptions {
GalleryOptions({ GalleryOptions({
this.themeMode, this.themeMode,
this.textScaleFactor, this.textScaleFactor,
this.visualDensity,
this.textDirection = TextDirection.ltr, this.textDirection = TextDirection.ltr,
this.timeDilation = 1.0, this.timeDilation = 1.0,
this.platform, this.platform,
...@@ -21,6 +22,7 @@ class GalleryOptions { ...@@ -21,6 +22,7 @@ class GalleryOptions {
final ThemeMode themeMode; final ThemeMode themeMode;
final GalleryTextScaleValue textScaleFactor; final GalleryTextScaleValue textScaleFactor;
final GalleryVisualDensityValue visualDensity;
final TextDirection textDirection; final TextDirection textDirection;
final double timeDilation; final double timeDilation;
final TargetPlatform platform; final TargetPlatform platform;
...@@ -31,6 +33,7 @@ class GalleryOptions { ...@@ -31,6 +33,7 @@ class GalleryOptions {
GalleryOptions copyWith({ GalleryOptions copyWith({
ThemeMode themeMode, ThemeMode themeMode,
GalleryTextScaleValue textScaleFactor, GalleryTextScaleValue textScaleFactor,
GalleryVisualDensityValue visualDensity,
TextDirection textDirection, TextDirection textDirection,
double timeDilation, double timeDilation,
TargetPlatform platform, TargetPlatform platform,
...@@ -41,6 +44,7 @@ class GalleryOptions { ...@@ -41,6 +44,7 @@ class GalleryOptions {
return GalleryOptions( return GalleryOptions(
themeMode: themeMode ?? this.themeMode, themeMode: themeMode ?? this.themeMode,
textScaleFactor: textScaleFactor ?? this.textScaleFactor, textScaleFactor: textScaleFactor ?? this.textScaleFactor,
visualDensity: visualDensity ?? this.visualDensity,
textDirection: textDirection ?? this.textDirection, textDirection: textDirection ?? this.textDirection,
timeDilation: timeDilation ?? this.timeDilation, timeDilation: timeDilation ?? this.timeDilation,
platform: platform ?? this.platform, platform: platform ?? this.platform,
...@@ -57,6 +61,7 @@ class GalleryOptions { ...@@ -57,6 +61,7 @@ class GalleryOptions {
return other is GalleryOptions return other is GalleryOptions
&& other.themeMode == themeMode && other.themeMode == themeMode
&& other.textScaleFactor == textScaleFactor && other.textScaleFactor == textScaleFactor
&& other.visualDensity == visualDensity
&& other.textDirection == textDirection && other.textDirection == textDirection
&& other.platform == platform && other.platform == platform
&& other.showPerformanceOverlay == showPerformanceOverlay && other.showPerformanceOverlay == showPerformanceOverlay
...@@ -68,6 +73,7 @@ class GalleryOptions { ...@@ -68,6 +73,7 @@ class GalleryOptions {
int get hashCode => hashValues( int get hashCode => hashValues(
themeMode, themeMode,
textScaleFactor, textScaleFactor,
visualDensity,
textDirection, textDirection,
timeDilation, timeDilation,
platform, platform,
...@@ -300,6 +306,52 @@ class _TextScaleFactorItem extends StatelessWidget { ...@@ -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 { class _TextDirectionItem extends StatelessWidget {
const _TextDirectionItem(this.options, this.onOptionsChanged); const _TextDirectionItem(this.options, this.onOptionsChanged);
...@@ -469,6 +521,7 @@ class GalleryOptionsPage extends StatelessWidget { ...@@ -469,6 +521,7 @@ class GalleryOptionsPage extends StatelessWidget {
const _Heading('Display'), const _Heading('Display'),
_ThemeModeItem(options, onOptionsChanged), _ThemeModeItem(options, onOptionsChanged),
_TextScaleFactorItem(options, onOptionsChanged), _TextScaleFactorItem(options, onOptionsChanged),
_VisualDensityItem(options, onOptionsChanged),
_TextDirectionItem(options, onOptionsChanged), _TextDirectionItem(options, onOptionsChanged),
_TimeDilationItem(options, onOptionsChanged), _TimeDilationItem(options, onOptionsChanged),
const Divider(), const Divider(),
......
...@@ -36,3 +36,34 @@ const List<GalleryTextScaleValue> kAllGalleryTextScaleValues = <GalleryTextScale ...@@ -36,3 +36,34 @@ const List<GalleryTextScaleValue> kAllGalleryTextScaleValues = <GalleryTextScale
GalleryTextScaleValue(1.3, 'Large'), GalleryTextScaleValue(1.3, 'Large'),
GalleryTextScaleValue(2.0, 'Huge'), 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() { ...@@ -54,16 +54,40 @@ void main() {
// Switch back to system theme setting: first menu button, choose 'System Default' // Switch back to system theme setting: first menu button, choose 'System Default'
await tester.tap(find.byIcon(Icons.arrow_drop_down).first); await tester.tap(find.byIcon(Icons.arrow_drop_down).first);
await tester.pumpAndSettle(); 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(); await tester.pumpAndSettle();
app = find.byType(MaterialApp).evaluate().first.widget as MaterialApp; app = find.byType(MaterialApp).evaluate().first.widget as MaterialApp;
expect(app.themeMode, ThemeMode.system); 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 // Verify platform settings
expect(app.theme.platform, equals(TargetPlatform.android)); expect(app.theme.platform, equals(TargetPlatform.android));
// Popup the platform menu: third menu button, choose 'Cupertino' // Popup the platform menu: fourth menu button, choose 'Cupertino'
await tester.tap(find.byIcon(Icons.arrow_drop_down).at(2)); await tester.tap(find.byIcon(Icons.arrow_drop_down).at(3));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
await tester.tap(find.text('Cupertino').at(1)); await tester.tap(find.text('Cupertino').at(1));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
...@@ -85,7 +109,10 @@ void main() { ...@@ -85,7 +109,10 @@ void main() {
// Set font scale back to the default. // Set font scale back to the default.
await tester.tap(find.byIcon(Icons.arrow_drop_down).at(1)); await tester.tap(find.byIcon(Icons.arrow_drop_down).at(1));
await tester.pumpAndSettle(); 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(); await tester.pumpAndSettle();
textSize = tester.getSize(find.text('Text size')); textSize = tester.getSize(find.text('Text size'));
expect(textSize, origTextSize); 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