Unverified Commit bc7ed36d authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Add visualDensity to checkbox, radio, icon button, and chip. (#46091)

This adds a visualDensity attribute to checkbox, radio, icon button, and chip.
parent e6fa5717
......@@ -116,12 +116,12 @@ class OptionModel extends ChangeNotifier {
void reset() {
final OptionModel defaultModel = OptionModel();
_size = defaultModel._size;
_enable = defaultModel._enable;
_slowAnimations = defaultModel._slowAnimations;
_longText = defaultModel._longText;
_density = defaultModel._density;
_rtl = defaultModel._rtl;
_size = defaultModel.size;
_enable = defaultModel.enable;
_slowAnimations = defaultModel.slowAnimations;
_longText = defaultModel.longText;
_density = defaultModel.density;
_rtl = defaultModel.rtl;
notifyListeners();
}
}
......@@ -190,11 +190,9 @@ class _OptionsState extends State<Options> {
String _densityToProfile(VisualDensity density) {
if (density == VisualDensity.standard) {
return 'standard';
}
if (density == VisualDensity.compact) {
} else if (density == VisualDensity.compact) {
return 'compact';
}
if (density == VisualDensity.comfortable) {
} else if (density == VisualDensity.comfortable) {
return 'comfortable';
}
return 'custom';
......@@ -239,13 +237,14 @@ class _OptionsState extends State<Options> {
child: SliderTheme(
data: controlTheme,
child: Slider(
label: '${widget.model.size}',
min: 0.5,
max: 3.0,
onChanged: (double value) {
widget.model.size = value;
},
value: widget.model.size),
label: '${widget.model.size}',
min: 0.5,
max: 3.0,
onChanged: (double value) {
widget.model.size = value;
},
value: widget.model.size,
),
),
),
Text(
......@@ -264,13 +263,14 @@ class _OptionsState extends State<Options> {
child: SliderTheme(
data: controlTheme,
child: Slider(
label: '${widget.model.density.horizontal.toStringAsFixed(1)}',
min: VisualDensity.minimumDensity,
max: VisualDensity.maximumDensity,
onChanged: (double value) {
widget.model.density = widget.model.density.copyWith(horizontal: value, vertical: widget.model.density.vertical);
},
value: widget.model.density.horizontal),
label: '${widget.model.density.horizontal.toStringAsFixed(1)}',
min: VisualDensity.minimumDensity,
max: VisualDensity.maximumDensity,
onChanged: (double value) {
widget.model.density = widget.model.density.copyWith(horizontal: value, vertical: widget.model.density.vertical);
},
value: widget.model.density.horizontal,
),
),
),
Text(
......@@ -289,13 +289,14 @@ class _OptionsState extends State<Options> {
child: SliderTheme(
data: controlTheme,
child: Slider(
label: '${widget.model.density.vertical.toStringAsFixed(1)}',
min: VisualDensity.minimumDensity,
max: VisualDensity.maximumDensity,
onChanged: (double value) {
widget.model.density = widget.model.density.copyWith(horizontal: widget.model.density.horizontal, vertical: value);
},
value: widget.model.density.vertical),
label: '${widget.model.density.vertical.toStringAsFixed(1)}',
min: VisualDensity.minimumDensity,
max: VisualDensity.maximumDensity,
onChanged: (double value) {
widget.model.density = widget.model.density.copyWith(horizontal: widget.model.density.horizontal, vertical: value);
},
value: widget.model.density.vertical,
),
),
),
Text(
......@@ -318,7 +319,10 @@ class _OptionsState extends State<Options> {
widget.model.density = _profileToDensity(value);
},
items: const <DropdownMenuItem<String>>[
DropdownMenuItem<String>(child: Text('Standard'), value: 'standard',),
DropdownMenuItem<String>(
child: Text('Standard'),
value: 'standard',
),
DropdownMenuItem<String>(child: Text('Comfortable'), value: 'comfortable'),
DropdownMenuItem<String>(child: Text('Compact'), value: 'compact'),
DropdownMenuItem<String>(child: Text('Custom'), value: 'custom'),
......@@ -417,6 +421,10 @@ class _MyHomePageState extends State<MyHomePage> {
}
double sliderValue = 0.0;
List<bool> checkboxValues = <bool>[false, false, false, false];
List<IconData> iconValues = <IconData>[Icons.arrow_back, Icons.play_arrow, Icons.arrow_forward];
List<String> chipValues = <String>['Potato', 'Computer'];
int radioValue = 0;
@override
Widget build(BuildContext context) {
......@@ -426,6 +434,21 @@ class _MyHomePageState extends State<MyHomePage> {
final Widget label = Text(_model.rtl ? 'اضغط علي' : 'Press Me');
final List<Widget> tiles = <Widget>[
_ControlTile(
label: _model.rtl ? 'رقائق' : 'Chips',
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: List<Widget>.generate(chipValues.length, (int index) {
return InputChip(
onPressed: _model.enable ? () {} : null,
onDeleted: _model.enable ? () {} : null,
label: Text(chipValues[index]),
deleteIcon: const Icon(Icons.delete),
avatar: const Icon(Icons.play_arrow),
);
}),
),
),
_ControlTile(
label: _model.rtl ? 'زر المواد' : 'Material Button',
child: MaterialButton(
......@@ -458,6 +481,55 @@ class _MyHomePageState extends State<MyHomePage> {
child: label,
),
),
_ControlTile(
label: _model.rtl ? 'خانات الاختيار' : 'Checkboxes',
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List<Widget>.generate(checkboxValues.length, (int index) {
return Checkbox(
onChanged: _model.enable
? (bool value) {
setState(() {
checkboxValues[index] = value;
});
}
: null,
value: checkboxValues[index],
);
}),
),
),
_ControlTile(
label: _model.rtl ? 'زر الراديو' : 'Radio Button',
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List<Widget>.generate(4, (int index) {
return Radio<int>(
onChanged: _model.enable
? (int value) {
setState(() {
radioValue = value;
});
}
: null,
groupValue: radioValue,
value: index,
);
}),
),
),
_ControlTile(
label: _model.rtl ? 'زر الأيقونة' : 'Icon Button',
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List<Widget>.generate(iconValues.length, (int index) {
return IconButton(
onPressed: _model.enable ? () {} : null,
icon: Icon(iconValues[index]),
);
}),
),
),
];
return SafeArea(
......
......@@ -65,6 +65,7 @@ class Checkbox extends StatefulWidget {
this.focusColor,
this.hoverColor,
this.materialTapTargetSize,
this.visualDensity,
this.focusNode,
this.autofocus = false,
}) : assert(tristate != null),
......@@ -137,6 +138,16 @@ class Checkbox extends StatefulWidget {
/// * [MaterialTapTargetSize], for a description of how this affects tap targets.
final MaterialTapTargetSize materialTapTargetSize;
/// Defines how compact the checkbox's layout will be.
///
/// {@macro flutter.material.themedata.visualDensity}
///
/// See also:
///
/// * [ThemeData.visualDensity], which specifies the [density] for all widgets
/// within a [Theme].
final VisualDensity visualDensity;
/// The color for the checkbox's [Material] when it has the input focus.
final Color focusColor;
......@@ -220,6 +231,7 @@ class _CheckboxState extends State<Checkbox> with TickerProviderStateMixin {
size = const Size(2 * kRadialReactionRadius, 2 * kRadialReactionRadius);
break;
}
size += (widget.visualDensity ?? themeData.visualDensity).baseSizeAdjustment;
final BoxConstraints additionalConstraints = BoxConstraints.tight(size);
return FocusableActionDetector(
actions: _actionMap,
......
......@@ -117,6 +117,18 @@ abstract class ChipAttributes {
/// Defaults to 4 logical pixels on all sides.
EdgeInsetsGeometry get padding;
/// Defines how compact the chip's layout will be.
///
/// Chips are unaffected by horizontal density changes.
///
/// {@macro flutter.material.themedata.visualDensity}
///
/// See also:
///
/// * [ThemeData.visualDensity], which specifies the [density] for all widgets
/// within a [Theme].
VisualDensity get visualDensity;
/// The padding around the [label] widget.
///
/// By default, this is 4 logical pixels at the beginning and the end of the
......@@ -552,6 +564,7 @@ class Chip extends StatelessWidget implements ChipAttributes, DeletableChipAttri
this.autofocus = false,
this.backgroundColor,
this.padding,
this.visualDensity,
this.materialTapTargetSize,
this.elevation,
this.shadowColor,
......@@ -582,6 +595,8 @@ class Chip extends StatelessWidget implements ChipAttributes, DeletableChipAttri
@override
final EdgeInsetsGeometry padding;
@override
final VisualDensity visualDensity;
@override
final Widget deleteIcon;
@override
final VoidCallback onDeleted;
......@@ -615,6 +630,7 @@ class Chip extends StatelessWidget implements ChipAttributes, DeletableChipAttri
autofocus: autofocus,
backgroundColor: backgroundColor,
padding: padding,
visualDensity: visualDensity,
materialTapTargetSize: materialTapTargetSize,
elevation: elevation,
shadowColor: shadowColor,
......@@ -709,6 +725,7 @@ class InputChip extends StatelessWidget
this.autofocus = false,
this.backgroundColor,
this.padding,
this.visualDensity,
this.materialTapTargetSize,
this.elevation,
this.shadowColor,
......@@ -770,6 +787,8 @@ class InputChip extends StatelessWidget
@override
final EdgeInsetsGeometry padding;
@override
final VisualDensity visualDensity;
@override
final MaterialTapTargetSize materialTapTargetSize;
@override
final double elevation;
......@@ -810,6 +829,7 @@ class InputChip extends StatelessWidget
autofocus: autofocus,
backgroundColor: backgroundColor,
padding: padding,
visualDensity: visualDensity,
materialTapTargetSize: materialTapTargetSize,
elevation: elevation,
shadowColor: shadowColor,
......@@ -904,6 +924,7 @@ class ChoiceChip extends StatelessWidget
this.autofocus = false,
this.backgroundColor,
this.padding,
this.visualDensity,
this.materialTapTargetSize,
this.elevation,
this.shadowColor,
......@@ -950,6 +971,8 @@ class ChoiceChip extends StatelessWidget
@override
final EdgeInsetsGeometry padding;
@override
final VisualDensity visualDensity;
@override
final MaterialTapTargetSize materialTapTargetSize;
@override
final double elevation;
......@@ -986,6 +1009,7 @@ class ChoiceChip extends StatelessWidget
selectedColor: selectedColor ?? chipTheme.secondarySelectedColor,
backgroundColor: backgroundColor,
padding: padding,
visualDensity: visualDensity,
isEnabled: isEnabled,
materialTapTargetSize: materialTapTargetSize,
elevation: elevation,
......@@ -1111,6 +1135,7 @@ class FilterChip extends StatelessWidget
this.autofocus = false,
this.backgroundColor,
this.padding,
this.visualDensity,
this.materialTapTargetSize,
this.elevation,
this.shadowColor,
......@@ -1159,6 +1184,8 @@ class FilterChip extends StatelessWidget
@override
final EdgeInsetsGeometry padding;
@override
final VisualDensity visualDensity;
@override
final MaterialTapTargetSize materialTapTargetSize;
@override
final double elevation;
......@@ -1196,6 +1223,7 @@ class FilterChip extends StatelessWidget
disabledColor: disabledColor,
selectedColor: selectedColor,
padding: padding,
visualDensity: visualDensity,
isEnabled: isEnabled,
materialTapTargetSize: materialTapTargetSize,
elevation: elevation,
......@@ -1276,6 +1304,7 @@ class ActionChip extends StatelessWidget implements ChipAttributes, TappableChip
this.autofocus = false,
this.backgroundColor,
this.padding,
this.visualDensity,
this.materialTapTargetSize,
this.elevation,
this.shadowColor,
......@@ -1318,6 +1347,8 @@ class ActionChip extends StatelessWidget implements ChipAttributes, TappableChip
@override
final EdgeInsetsGeometry padding;
@override
final VisualDensity visualDensity;
@override
final MaterialTapTargetSize materialTapTargetSize;
@override
final double elevation;
......@@ -1340,6 +1371,7 @@ class ActionChip extends StatelessWidget implements ChipAttributes, TappableChip
focusNode: focusNode,
autofocus: autofocus,
padding: padding,
visualDensity: visualDensity,
labelPadding: labelPadding,
isEnabled: true,
materialTapTargetSize: materialTapTargetSize,
......@@ -1402,6 +1434,7 @@ class RawChip extends StatefulWidget
@required this.label,
this.labelStyle,
this.padding,
this.visualDensity,
this.labelPadding,
Widget deleteIcon,
this.onDeleted,
......@@ -1483,6 +1516,8 @@ class RawChip extends StatefulWidget
@override
final EdgeInsetsGeometry padding;
@override
final VisualDensity visualDensity;
@override
final MaterialTapTargetSize materialTapTargetSize;
@override
final double elevation;
......@@ -1846,6 +1881,7 @@ class _RawChipState extends State<RawChip> with TickerProviderStateMixin<RawChip
),
brightness: chipTheme.brightness,
padding: (widget.padding ?? chipTheme.padding).resolve(textDirection),
visualDensity: widget.visualDensity ?? theme.visualDensity,
labelPadding: (widget.labelPadding ?? chipTheme.labelPadding).resolve(textDirection),
showAvatar: hasAvatar,
showCheckmark: showCheckmark,
......@@ -1865,9 +1901,10 @@ class _RawChipState extends State<RawChip> with TickerProviderStateMixin<RawChip
),
);
BoxConstraints constraints;
final Offset densityAdjustment = (widget.visualDensity ?? theme.visualDensity).baseSizeAdjustment;
switch (widget.materialTapTargetSize ?? theme.materialTapTargetSize) {
case MaterialTapTargetSize.padded:
constraints = const BoxConstraints(minHeight: kMinInteractiveDimension);
constraints = BoxConstraints(minHeight: kMinInteractiveDimension + densityAdjustment.dy);
break;
case MaterialTapTargetSize.shrinkWrap:
constraints = const BoxConstraints();
......@@ -2114,6 +2151,7 @@ class _ChipRenderTheme {
@required this.deleteIcon,
@required this.brightness,
@required this.padding,
@required this.visualDensity,
@required this.labelPadding,
@required this.showAvatar,
@required this.showCheckmark,
......@@ -2126,6 +2164,7 @@ class _ChipRenderTheme {
final Widget deleteIcon;
final Brightness brightness;
final EdgeInsets padding;
final VisualDensity visualDensity;
final EdgeInsets labelPadding;
final bool showAvatar;
final bool showCheckmark;
......@@ -2492,6 +2531,7 @@ class _RenderChip extends RenderBox {
void performLayout() {
final BoxConstraints contentConstraints = constraints.loosen();
// Find out the height of the label within the constraints.
final Offset densityAdjustment = Offset(0.0, theme.visualDensity.baseSizeAdjustment.dy / 2.0);
label.layout(contentConstraints, parentUsesSize: true);
final double contentSize = math.max(
_kChipHeight - theme.padding.vertical + theme.labelPadding.vertical,
......@@ -2507,7 +2547,7 @@ class _RenderChip extends RenderBox {
final Size overallSize = Size(
avatarSize.width + labelSize.width + deleteIconSize.width,
contentSize,
);
) + densityAdjustment;
// Now we have all of the dimensions. Place the children where they belong.
......@@ -2519,10 +2559,10 @@ class _RenderChip extends RenderBox {
Offset boxOffset;
switch (textDirection) {
case TextDirection.rtl:
boxOffset = Offset(x - boxSize.width, (contentSize - boxSize.height) / 2.0);
boxOffset = Offset(x - boxSize.width, (contentSize - boxSize.height + densityAdjustment.dy) / 2.0);
break;
case TextDirection.ltr:
boxOffset = Offset(x, (contentSize - boxSize.height) / 2.0);
boxOffset = Offset(x, (contentSize - boxSize.height + densityAdjustment.dy) / 2.0);
break;
}
return boxOffset;
......
......@@ -13,6 +13,7 @@ import 'icons.dart';
import 'ink_well.dart';
import 'material.dart';
import 'theme.dart';
import 'theme_data.dart';
import 'tooltip.dart';
// Minimum logical pixel size of the IconButton.
......@@ -138,6 +139,7 @@ class IconButton extends StatelessWidget {
const IconButton({
Key key,
this.iconSize = 24.0,
this.visualDensity,
this.padding = const EdgeInsets.all(8.0),
this.alignment = Alignment.center,
@required this.icon,
......@@ -171,6 +173,16 @@ class IconButton extends StatelessWidget {
/// the [Icon] itself would likely get clipped.
final double iconSize;
/// Defines how compact the icon button's layout will be.
///
/// {@macro flutter.material.themedata.visualDensity}
///
/// See also:
///
/// * [ThemeData.visualDensity], which specifies the [density] for all widgets
/// within a [Theme].
final VisualDensity visualDensity;
/// The padding around the button's icon. The entire padded icon will react
/// to input gestures.
///
......@@ -279,14 +291,16 @@ class IconButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
assert(debugCheckHasMaterial(context));
final ThemeData theme = Theme.of(context);
Color currentColor;
if (onPressed != null)
currentColor = color;
else
currentColor = disabledColor ?? Theme.of(context).disabledColor;
currentColor = disabledColor ?? theme.disabledColor;
final Offset densityAdjustment = (visualDensity ?? theme.visualDensity).baseSizeAdjustment;
Widget result = ConstrainedBox(
constraints: const BoxConstraints(minWidth: _kMinButtonSize, minHeight: _kMinButtonSize),
constraints: BoxConstraints(minWidth: _kMinButtonSize + densityAdjustment.dx, minHeight: _kMinButtonSize + densityAdjustment.dy),
child: Padding(
padding: padding,
child: SizedBox(
......
......@@ -112,6 +112,7 @@ class Radio<T> extends StatefulWidget {
this.focusColor,
this.hoverColor,
this.materialTapTargetSize,
this.visualDensity,
this.focusNode,
this.autofocus = false,
}) : assert(autofocus != null),
......@@ -168,6 +169,16 @@ class Radio<T> extends StatefulWidget {
/// * [MaterialTapTargetSize], for a description of how this affects tap targets.
final MaterialTapTargetSize materialTapTargetSize;
/// Defines how compact the radio's layout will be.
///
/// {@macro flutter.material.themedata.visualDensity}
///
/// See also:
///
/// * [ThemeData.visualDensity], which specifies the [density] for all widgets
/// within a [Theme].
final VisualDensity visualDensity;
/// The color for the radio's [Material] when it has the input focus.
final Color focusColor;
......@@ -247,6 +258,7 @@ class _RadioState<T> extends State<Radio<T>> with TickerProviderStateMixin {
size = const Size(2 * kRadialReactionRadius, 2 * kRadialReactionRadius);
break;
}
size += (widget.visualDensity ?? themeData.visualDensity).baseSizeAdjustment;
final BoxConstraints additionalConstraints = BoxConstraints.tight(size);
return FocusableActionDetector(
actions: _actionMap,
......
......@@ -565,4 +565,41 @@ void main() {
await tester.pumpAndSettle();
expect(value, isTrue);
});
testWidgets('Checkbox responds to density changes.', (WidgetTester tester) async {
const Key key = Key('test');
Future<void> buildTest(VisualDensity visualDensity) async {
return await tester.pumpWidget(
MaterialApp(
home: Material(
child: Center(
child: Checkbox(
visualDensity: visualDensity,
key: key,
onChanged: (bool value) {},
value: true,
),
),
),
),
);
}
await buildTest(const VisualDensity());
final RenderBox box = tester.renderObject(find.byKey(key));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(48, 48)));
await buildTest(const VisualDensity(horizontal: 3.0, vertical: 3.0));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(60, 60)));
await buildTest(const VisualDensity(horizontal: -3.0, vertical: -3.0));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(36, 36)));
await buildTest(const VisualDensity(horizontal: 3.0, vertical: -3.0));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(60, 36)));
});
}
......@@ -474,7 +474,7 @@ void main() {
),
);
expect(tester.getSize(find.byType(Text)), const Size(40.0, 10.0));
expect(tester.getSize(find.byType(Chip)), const Size(64.0,48.0));
expect(tester.getSize(find.byType(Chip)), const Size(64.0, 48.0));
await tester.pumpWidget(
_wrapForChip(
child: Row(
......@@ -2245,6 +2245,111 @@ void main() {
expect(focusNode2.hasPrimaryFocus, isFalse);
});
testWidgets('Chip responds to density changes.', (WidgetTester tester) async {
const Key key = Key('test');
const Key textKey = Key('test text');
const Key iconKey = Key('test icon');
const Key avatarKey = Key('test avatar');
Future<void> buildTest(VisualDensity visualDensity) async {
return await tester.pumpWidget(
MaterialApp(
home: Material(
child: Center(
child: Column(
children: <Widget>[
InputChip(
visualDensity: visualDensity,
key: key,
onPressed: () {},
onDeleted: () {},
label: const Text('Test', key: textKey),
deleteIcon: const Icon(Icons.delete, key: iconKey),
avatar: const Icon(Icons.play_arrow, key: avatarKey),
),
],
),
),
),
),
);
}
// The Chips only change in size vertically in response to density, so
// horizontal changes aren't expected.
await buildTest(VisualDensity.standard);
Rect box = tester.getRect(find.byKey(key));
Rect textBox = tester.getRect(find.byKey(textKey));
Rect iconBox = tester.getRect(find.byKey(iconKey));
Rect avatarBox = tester.getRect(find.byKey(avatarKey));
expect(box.size, equals(const Size(128, 32.0 + 16.0)));
expect(textBox.size, equals(const Size(56, 14)));
expect(iconBox.size, equals(const Size(24, 24)));
expect(avatarBox.size, equals(const Size(24, 24)));
expect(textBox.top, equals(17));
expect(box.bottom - textBox.bottom, equals(17));
expect(textBox.left, equals(372));
expect(box.right - textBox.right, equals(36));
// Try decreasing density (with higher density numbers).
await buildTest(const VisualDensity(horizontal: 3.0, vertical: 3.0));
box = tester.getRect(find.byKey(key));
textBox = tester.getRect(find.byKey(textKey));
iconBox = tester.getRect(find.byKey(iconKey));
avatarBox = tester.getRect(find.byKey(avatarKey));
expect(box.size, equals(const Size(128, 60)));
expect(textBox.size, equals(const Size(56, 14)));
expect(iconBox.size, equals(const Size(24, 24)));
expect(avatarBox.size, equals(const Size(24, 24)));
expect(textBox.top, equals(23));
expect(box.bottom - textBox.bottom, equals(23));
expect(textBox.left, equals(372));
expect(box.right - textBox.right, equals(36));
// Try increasing density (with lower density numbers).
await buildTest(const VisualDensity(horizontal: -3.0, vertical: -3.0));
box = tester.getRect(find.byKey(key));
textBox = tester.getRect(find.byKey(textKey));
iconBox = tester.getRect(find.byKey(iconKey));
avatarBox = tester.getRect(find.byKey(avatarKey));
expect(box.size, equals(const Size(128, 36)));
expect(textBox.size, equals(const Size(56, 14)));
expect(iconBox.size, equals(const Size(24, 24)));
expect(avatarBox.size, equals(const Size(24, 24)));
expect(textBox.top, equals(11));
expect(box.bottom - textBox.bottom, equals(11));
expect(textBox.left, equals(372));
expect(box.right - textBox.right, equals(36));
// Now test that horizontal and vertical are wired correctly. Negating the
// horizontal should have no change over what's above.
await buildTest(const VisualDensity(horizontal: 3.0, vertical: -3.0));
await tester.pumpAndSettle();
box = tester.getRect(find.byKey(key));
textBox = tester.getRect(find.byKey(textKey));
iconBox = tester.getRect(find.byKey(iconKey));
avatarBox = tester.getRect(find.byKey(avatarKey));
expect(box.size, equals(const Size(128, 36)));
expect(textBox.size, equals(const Size(56, 14)));
expect(iconBox.size, equals(const Size(24, 24)));
expect(avatarBox.size, equals(const Size(24, 24)));
expect(textBox.top, equals(11));
expect(box.bottom - textBox.bottom, equals(11));
expect(textBox.left, equals(372));
expect(box.right - textBox.right, equals(36));
// Make sure the "Comfortable" setting is the spec'd size
await buildTest(VisualDensity.comfortable);
await tester.pumpAndSettle();
box = tester.getRect(find.byKey(key));
expect(box.size, equals(const Size(128, 28.0 + 16.0)));
// Make sure the "Compact" setting is the spec'd size
await buildTest(VisualDensity.compact);
await tester.pumpAndSettle();
box = tester.getRect(find.byKey(key));
expect(box.size, equals(const Size(128, 24.0 + 16.0)));
});
testWidgets('Input chip check mark color is determined by platform brightness when light', (WidgetTester tester) async {
await _pumpCheckmarkChip(
tester,
......
......@@ -467,6 +467,43 @@ void main() {
expect(feedback.hapticCount, 0);
});
});
testWidgets('IconButton responds to density changes.', (WidgetTester tester) async {
const Key key = Key('test');
Future<void> buildTest(VisualDensity visualDensity) async {
return await tester.pumpWidget(
MaterialApp(
home: Material(
child: Center(
child: IconButton(
visualDensity: visualDensity,
key: key,
onPressed: () {},
icon: const Icon(Icons.play_arrow),
),
),
),
),
);
}
await buildTest(const VisualDensity());
final RenderBox box = tester.renderObject(find.byKey(key));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(48, 48)));
await buildTest(const VisualDensity(horizontal: 3.0, vertical: 3.0));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(60, 60)));
await buildTest(const VisualDensity(horizontal: -3.0, vertical: -3.0));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(40, 40)));
await buildTest(const VisualDensity(horizontal: 3.0, vertical: -3.0));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(60, 40)));
});
}
Widget wrap({ Widget child }) {
......
......@@ -521,4 +521,41 @@ void main() {
expect(groupValue, equals(2));
});
testWidgets('Radio responds to density changes.', (WidgetTester tester) async {
const Key key = Key('test');
Future<void> buildTest(VisualDensity visualDensity) async {
return await tester.pumpWidget(
MaterialApp(
home: Material(
child: Center(
child: Radio<int>(
visualDensity: visualDensity,
key: key,
onChanged: (int value) {},
value: 0,
groupValue: 0,
),
),
),
),
);
}
await buildTest(const VisualDensity());
final RenderBox box = tester.renderObject(find.byKey(key));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(48, 48)));
await buildTest(const VisualDensity(horizontal: 3.0, vertical: 3.0));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(60, 60)));
await buildTest(const VisualDensity(horizontal: -3.0, vertical: -3.0));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(36, 36)));
await buildTest(const VisualDensity(horizontal: 3.0, vertical: -3.0));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(60, 36)));
});
}
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