Unverified Commit 185da9b0 authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Add Density API to ThemeData, implement for buttons. (#43547)

* Add a density attribute to ThemeData

* Simplify tests

* Review changes (Hans)
parent 1ac17c14
...@@ -52,6 +52,7 @@ class RawMaterialButton extends StatefulWidget { ...@@ -52,6 +52,7 @@ class RawMaterialButton extends StatefulWidget {
this.highlightElevation = 8.0, this.highlightElevation = 8.0,
this.disabledElevation = 0.0, this.disabledElevation = 0.0,
this.padding = EdgeInsets.zero, this.padding = EdgeInsets.zero,
this.visualDensity = const VisualDensity(),
this.constraints = const BoxConstraints(minWidth: 88.0, minHeight: 36.0), this.constraints = const BoxConstraints(minWidth: 88.0, minHeight: 36.0),
this.shape = const RoundedRectangleBorder(), this.shape = const RoundedRectangleBorder(),
this.animationDuration = kThemeChangeDuration, this.animationDuration = kThemeChangeDuration,
...@@ -207,6 +208,16 @@ class RawMaterialButton extends StatefulWidget { ...@@ -207,6 +208,16 @@ class RawMaterialButton extends StatefulWidget {
/// The internal padding for the button's [child]. /// The internal padding for the button's [child].
final EdgeInsetsGeometry padding; final EdgeInsetsGeometry padding;
/// Defines how compact the button's layout will be.
///
/// {@macro flutter.material.themedata.visualDensity}
///
/// See also:
///
/// * [ThemeData.visualDensity], which specifies the [visualDensity] for all widgets
/// within a [Theme].
final VisualDensity visualDensity;
/// Defines the button's size. /// Defines the button's size.
/// ///
/// Typically used to constrain the button's minimum size. /// Typically used to constrain the button's minimum size.
...@@ -354,9 +365,22 @@ class _RawMaterialButtonState extends State<RawMaterialButton> { ...@@ -354,9 +365,22 @@ class _RawMaterialButtonState extends State<RawMaterialButton> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final Color effectiveTextColor = MaterialStateProperty.resolveAs<Color>(widget.textStyle?.color, _states); final Color effectiveTextColor = MaterialStateProperty.resolveAs<Color>(widget.textStyle?.color, _states);
final ShapeBorder effectiveShape = MaterialStateProperty.resolveAs<ShapeBorder>(widget.shape, _states); final ShapeBorder effectiveShape = MaterialStateProperty.resolveAs<ShapeBorder>(widget.shape, _states);
final Offset densityAdjustment = widget.visualDensity.baseSizeAdjustment;
final BoxConstraints effectiveConstraints = widget.constraints.copyWith(
minWidth: widget.constraints.minWidth != null ? (widget.constraints.minWidth + densityAdjustment.dx).clamp(0.0, double.infinity) : null,
minHeight: widget.constraints.minWidth != null ? (widget.constraints.minHeight + densityAdjustment.dy).clamp(0.0, double.infinity) : null,
);
final EdgeInsetsGeometry padding = widget.padding.add(
EdgeInsets.only(
left: densityAdjustment.dx,
top: densityAdjustment.dy,
right: densityAdjustment.dx,
bottom: densityAdjustment.dy,
),
).clamp(EdgeInsets.zero, EdgeInsetsGeometry.infinity);
final Widget result = ConstrainedBox( final Widget result = ConstrainedBox(
constraints: widget.constraints, constraints: effectiveConstraints,
child: Material( child: Material(
elevation: _effectiveElevation, elevation: _effectiveElevation,
textStyle: widget.textStyle?.copyWith(color: effectiveTextColor), textStyle: widget.textStyle?.copyWith(color: effectiveTextColor),
...@@ -383,7 +407,7 @@ class _RawMaterialButtonState extends State<RawMaterialButton> { ...@@ -383,7 +407,7 @@ class _RawMaterialButtonState extends State<RawMaterialButton> {
child: IconTheme.merge( child: IconTheme.merge(
data: IconThemeData(color: effectiveTextColor), data: IconThemeData(color: effectiveTextColor),
child: Container( child: Container(
padding: widget.padding, padding: padding,
child: Center( child: Center(
widthFactor: 1.0, widthFactor: 1.0,
heightFactor: 1.0, heightFactor: 1.0,
...@@ -397,7 +421,12 @@ class _RawMaterialButtonState extends State<RawMaterialButton> { ...@@ -397,7 +421,12 @@ class _RawMaterialButtonState extends State<RawMaterialButton> {
Size minSize; Size minSize;
switch (widget.materialTapTargetSize) { switch (widget.materialTapTargetSize) {
case MaterialTapTargetSize.padded: case MaterialTapTargetSize.padded:
minSize = const Size(48.0, 48.0); minSize = Size(
kMinInteractiveDimension + densityAdjustment.dx,
kMinInteractiveDimension + densityAdjustment.dy,
);
assert(minSize.width >= 0.0);
assert(minSize.height >= 0.0);
break; break;
case MaterialTapTargetSize.shrinkWrap: case MaterialTapTargetSize.shrinkWrap:
minSize = Size.zero; minSize = Size.zero;
......
...@@ -115,6 +115,7 @@ class FlatButton extends MaterialButton { ...@@ -115,6 +115,7 @@ class FlatButton extends MaterialButton {
Color splashColor, Color splashColor,
Brightness colorBrightness, Brightness colorBrightness,
EdgeInsetsGeometry padding, EdgeInsetsGeometry padding,
VisualDensity visualDensity,
ShapeBorder shape, ShapeBorder shape,
Clip clipBehavior = Clip.none, Clip clipBehavior = Clip.none,
FocusNode focusNode, FocusNode focusNode,
...@@ -139,6 +140,7 @@ class FlatButton extends MaterialButton { ...@@ -139,6 +140,7 @@ class FlatButton extends MaterialButton {
splashColor: splashColor, splashColor: splashColor,
colorBrightness: colorBrightness, colorBrightness: colorBrightness,
padding: padding, padding: padding,
visualDensity: visualDensity,
shape: shape, shape: shape,
clipBehavior: clipBehavior, clipBehavior: clipBehavior,
focusNode: focusNode, focusNode: focusNode,
...@@ -199,6 +201,7 @@ class FlatButton extends MaterialButton { ...@@ -199,6 +201,7 @@ class FlatButton extends MaterialButton {
highlightElevation: buttonTheme.getHighlightElevation(this), highlightElevation: buttonTheme.getHighlightElevation(this),
disabledElevation: buttonTheme.getDisabledElevation(this), disabledElevation: buttonTheme.getDisabledElevation(this),
padding: buttonTheme.getPadding(this), padding: buttonTheme.getPadding(this),
visualDensity: visualDensity ?? theme.visualDensity,
constraints: buttonTheme.getConstraints(this), constraints: buttonTheme.getConstraints(this),
shape: buttonTheme.getShape(this), shape: buttonTheme.getShape(this),
clipBehavior: clipBehavior, clipBehavior: clipBehavior,
......
...@@ -69,6 +69,7 @@ class MaterialButton extends StatelessWidget { ...@@ -69,6 +69,7 @@ class MaterialButton extends StatelessWidget {
this.highlightElevation, this.highlightElevation,
this.disabledElevation, this.disabledElevation,
this.padding, this.padding,
this.visualDensity,
this.shape, this.shape,
this.clipBehavior = Clip.none, this.clipBehavior = Clip.none,
this.focusNode, this.focusNode,
...@@ -311,6 +312,16 @@ class MaterialButton extends StatelessWidget { ...@@ -311,6 +312,16 @@ class MaterialButton extends StatelessWidget {
/// [ButtonThemeData.padding]. /// [ButtonThemeData.padding].
final EdgeInsetsGeometry padding; final EdgeInsetsGeometry padding;
/// Defines how compact the 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 shape of the button's [Material]. /// The shape of the button's [Material].
/// ///
/// The button's highlight and splash are clipped to this shape. If the /// The button's highlight and splash are clipped to this shape. If the
...@@ -387,6 +398,7 @@ class MaterialButton extends StatelessWidget { ...@@ -387,6 +398,7 @@ class MaterialButton extends StatelessWidget {
hoverElevation: buttonTheme.getHoverElevation(this), hoverElevation: buttonTheme.getHoverElevation(this),
highlightElevation: buttonTheme.getHighlightElevation(this), highlightElevation: buttonTheme.getHighlightElevation(this),
padding: buttonTheme.getPadding(this), padding: buttonTheme.getPadding(this),
visualDensity: visualDensity ?? theme.visualDensity,
constraints: buttonTheme.getConstraints(this).copyWith( constraints: buttonTheme.getConstraints(this).copyWith(
minWidth: minWidth, minWidth: minWidth,
minHeight: height, minHeight: height,
...@@ -416,6 +428,7 @@ class MaterialButton extends StatelessWidget { ...@@ -416,6 +428,7 @@ class MaterialButton extends StatelessWidget {
properties.add(ColorProperty('splashColor', splashColor, defaultValue: null)); properties.add(ColorProperty('splashColor', splashColor, defaultValue: null));
properties.add(DiagnosticsProperty<Brightness>('colorBrightness', colorBrightness, defaultValue: null)); properties.add(DiagnosticsProperty<Brightness>('colorBrightness', colorBrightness, defaultValue: null));
properties.add(DiagnosticsProperty<EdgeInsetsGeometry>('padding', padding, defaultValue: null)); properties.add(DiagnosticsProperty<EdgeInsetsGeometry>('padding', padding, defaultValue: null));
properties.add(DiagnosticsProperty<VisualDensity>('visualDensity', visualDensity, defaultValue: null));
properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null)); properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null));
properties.add(DiagnosticsProperty<FocusNode>('focusNode', focusNode, defaultValue: null)); properties.add(DiagnosticsProperty<FocusNode>('focusNode', focusNode, defaultValue: null));
properties.add(DiagnosticsProperty<MaterialTapTargetSize>('materialTapTargetSize', materialTapTargetSize, defaultValue: null)); properties.add(DiagnosticsProperty<MaterialTapTargetSize>('materialTapTargetSize', materialTapTargetSize, defaultValue: null));
......
...@@ -11,6 +11,7 @@ import 'material_button.dart'; ...@@ -11,6 +11,7 @@ import 'material_button.dart';
import 'material_state.dart'; import 'material_state.dart';
import 'raised_button.dart'; import 'raised_button.dart';
import 'theme.dart'; import 'theme.dart';
import 'theme_data.dart';
// The total time to make the button's fill color opaque and change // The total time to make the button's fill color opaque and change
// its elevation. Only applies when highlightElevation > 0.0. // its elevation. Only applies when highlightElevation > 0.0.
...@@ -75,6 +76,7 @@ class OutlineButton extends MaterialButton { ...@@ -75,6 +76,7 @@ class OutlineButton extends MaterialButton {
this.disabledBorderColor, this.disabledBorderColor,
this.highlightedBorderColor, this.highlightedBorderColor,
EdgeInsetsGeometry padding, EdgeInsetsGeometry padding,
VisualDensity visualDensity,
ShapeBorder shape, ShapeBorder shape,
Clip clipBehavior = Clip.none, Clip clipBehavior = Clip.none,
FocusNode focusNode, FocusNode focusNode,
...@@ -97,6 +99,7 @@ class OutlineButton extends MaterialButton { ...@@ -97,6 +99,7 @@ class OutlineButton extends MaterialButton {
splashColor: splashColor, splashColor: splashColor,
highlightElevation: highlightElevation, highlightElevation: highlightElevation,
padding: padding, padding: padding,
visualDensity: visualDensity,
shape: shape, shape: shape,
clipBehavior: clipBehavior, clipBehavior: clipBehavior,
focusNode: focusNode, focusNode: focusNode,
...@@ -129,6 +132,7 @@ class OutlineButton extends MaterialButton { ...@@ -129,6 +132,7 @@ class OutlineButton extends MaterialButton {
Color disabledBorderColor, Color disabledBorderColor,
BorderSide borderSide, BorderSide borderSide,
EdgeInsetsGeometry padding, EdgeInsetsGeometry padding,
VisualDensity visualDensity,
ShapeBorder shape, ShapeBorder shape,
Clip clipBehavior, Clip clipBehavior,
FocusNode focusNode, FocusNode focusNode,
...@@ -187,6 +191,7 @@ class OutlineButton extends MaterialButton { ...@@ -187,6 +191,7 @@ class OutlineButton extends MaterialButton {
disabledBorderColor: disabledBorderColor, disabledBorderColor: disabledBorderColor,
highlightedBorderColor: highlightedBorderColor ?? buttonTheme.colorScheme.primary, highlightedBorderColor: highlightedBorderColor ?? buttonTheme.colorScheme.primary,
padding: buttonTheme.getPadding(this), padding: buttonTheme.getPadding(this),
visualDensity: visualDensity,
shape: buttonTheme.getShape(this), shape: buttonTheme.getShape(this),
clipBehavior: clipBehavior, clipBehavior: clipBehavior,
focusNode: focusNode, focusNode: focusNode,
...@@ -225,6 +230,7 @@ class _OutlineButtonWithIcon extends OutlineButton with MaterialButtonWithIconMi ...@@ -225,6 +230,7 @@ class _OutlineButtonWithIcon extends OutlineButton with MaterialButtonWithIconMi
Color disabledBorderColor, Color disabledBorderColor,
BorderSide borderSide, BorderSide borderSide,
EdgeInsetsGeometry padding, EdgeInsetsGeometry padding,
VisualDensity visualDensity,
ShapeBorder shape, ShapeBorder shape,
Clip clipBehavior = Clip.none, Clip clipBehavior = Clip.none,
FocusNode focusNode, FocusNode focusNode,
...@@ -253,6 +259,7 @@ class _OutlineButtonWithIcon extends OutlineButton with MaterialButtonWithIconMi ...@@ -253,6 +259,7 @@ class _OutlineButtonWithIcon extends OutlineButton with MaterialButtonWithIconMi
highlightedBorderColor: highlightedBorderColor, highlightedBorderColor: highlightedBorderColor,
borderSide: borderSide, borderSide: borderSide,
padding: padding, padding: padding,
visualDensity: visualDensity,
shape: shape, shape: shape,
clipBehavior: clipBehavior, clipBehavior: clipBehavior,
focusNode: focusNode, focusNode: focusNode,
...@@ -287,6 +294,7 @@ class _OutlineButton extends StatefulWidget { ...@@ -287,6 +294,7 @@ class _OutlineButton extends StatefulWidget {
this.disabledBorderColor, this.disabledBorderColor,
@required this.highlightedBorderColor, @required this.highlightedBorderColor,
this.padding, this.padding,
this.visualDensity,
this.shape, this.shape,
this.clipBehavior = Clip.none, this.clipBehavior = Clip.none,
this.focusNode, this.focusNode,
...@@ -314,6 +322,7 @@ class _OutlineButton extends StatefulWidget { ...@@ -314,6 +322,7 @@ class _OutlineButton extends StatefulWidget {
final Color disabledBorderColor; final Color disabledBorderColor;
final Color highlightedBorderColor; final Color highlightedBorderColor;
final EdgeInsetsGeometry padding; final EdgeInsetsGeometry padding;
final VisualDensity visualDensity;
final ShapeBorder shape; final ShapeBorder shape;
final Clip clipBehavior; final Clip clipBehavior;
final FocusNode focusNode; final FocusNode focusNode;
...@@ -435,6 +444,8 @@ class _OutlineButtonState extends State<_OutlineButton> with SingleTickerProvide ...@@ -435,6 +444,8 @@ class _OutlineButtonState extends State<_OutlineButton> with SingleTickerProvide
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
return AnimatedBuilder( return AnimatedBuilder(
animation: _controller, animation: _controller,
builder: (BuildContext context, Widget child) { builder: (BuildContext context, Widget child) {
...@@ -456,6 +467,7 @@ class _OutlineButtonState extends State<_OutlineButton> with SingleTickerProvide ...@@ -456,6 +467,7 @@ class _OutlineButtonState extends State<_OutlineButton> with SingleTickerProvide
highlightElevation: _getHighlightElevation(), highlightElevation: _getHighlightElevation(),
onHighlightChanged: _handleHighlightChanged, onHighlightChanged: _handleHighlightChanged,
padding: widget.padding, padding: widget.padding,
visualDensity: widget.visualDensity ?? theme.visualDensity,
shape: _OutlineBorder( shape: _OutlineBorder(
shape: widget.shape, shape: widget.shape,
side: _getOutline(), side: _getOutline(),
......
...@@ -126,6 +126,7 @@ class RaisedButton extends MaterialButton { ...@@ -126,6 +126,7 @@ class RaisedButton extends MaterialButton {
double highlightElevation, double highlightElevation,
double disabledElevation, double disabledElevation,
EdgeInsetsGeometry padding, EdgeInsetsGeometry padding,
VisualDensity visualDensity,
ShapeBorder shape, ShapeBorder shape,
Clip clipBehavior = Clip.none, Clip clipBehavior = Clip.none,
FocusNode focusNode, FocusNode focusNode,
...@@ -161,6 +162,7 @@ class RaisedButton extends MaterialButton { ...@@ -161,6 +162,7 @@ class RaisedButton extends MaterialButton {
highlightElevation: highlightElevation, highlightElevation: highlightElevation,
disabledElevation: disabledElevation, disabledElevation: disabledElevation,
padding: padding, padding: padding,
visualDensity: visualDensity,
shape: shape, shape: shape,
clipBehavior: clipBehavior, clipBehavior: clipBehavior,
focusNode: focusNode, focusNode: focusNode,
...@@ -227,6 +229,7 @@ class RaisedButton extends MaterialButton { ...@@ -227,6 +229,7 @@ class RaisedButton extends MaterialButton {
highlightElevation: buttonTheme.getHighlightElevation(this), highlightElevation: buttonTheme.getHighlightElevation(this),
disabledElevation: buttonTheme.getDisabledElevation(this), disabledElevation: buttonTheme.getDisabledElevation(this),
padding: buttonTheme.getPadding(this), padding: buttonTheme.getPadding(this),
visualDensity: visualDensity ?? theme.visualDensity,
constraints: buttonTheme.getConstraints(this), constraints: buttonTheme.getConstraints(this),
shape: buttonTheme.getShape(this), shape: buttonTheme.getShape(this),
focusNode: focusNode, focusNode: focusNode,
......
...@@ -34,6 +34,18 @@ abstract class EdgeInsetsGeometry { ...@@ -34,6 +34,18 @@ abstract class EdgeInsetsGeometry {
double get _start; double get _start;
double get _top; double get _top;
/// An [EdgeInsetsGeometry] with infinite offsets in each direction.
///
/// Can be used as an infinite upper bound for [clamp].
static const EdgeInsetsGeometry infinity = _MixedEdgeInsets.fromLRSETB(
double.infinity,
double.infinity,
double.infinity,
double.infinity,
double.infinity,
double.infinity,
);
/// Whether every dimension is non-negative. /// Whether every dimension is non-negative.
bool get isNonNegative { bool get isNonNegative {
return _left >= 0.0 return _left >= 0.0
...@@ -146,6 +158,19 @@ abstract class EdgeInsetsGeometry { ...@@ -146,6 +158,19 @@ abstract class EdgeInsetsGeometry {
); );
} }
/// Returns the a new [EdgeInsetsGeometry] object with all values greater than
/// or equal to `min`, and less than or equal to `max`.
EdgeInsetsGeometry clamp(EdgeInsetsGeometry min, EdgeInsetsGeometry max) {
return _MixedEdgeInsets.fromLRSETB(
_left.clamp(min._left, max._left),
_right.clamp(min._right, max._right),
_start.clamp(min._start, max._start),
_end.clamp(min._end, max._end),
_top.clamp(min._top, max._top),
_bottom.clamp(min._bottom, max._bottom),
);
}
/// Returns the [EdgeInsetsGeometry] object with each dimension negated. /// Returns the [EdgeInsetsGeometry] object with each dimension negated.
/// ///
/// This is the same as multiplying the object by -1.0. /// This is the same as multiplying the object by -1.0.
......
...@@ -690,6 +690,53 @@ void main() { ...@@ -690,6 +690,53 @@ void main() {
await tester.longPress(flatButton); await tester.longPress(flatButton);
expect(didLongPressButton, isTrue); expect(didLongPressButton, isTrue);
}); });
testWidgets('FlatButton responds to density changes.', (WidgetTester tester) async {
const Key key = Key('test');
Future<void> buildTest(VisualDensity visualDensity, {bool useText = false}) async {
return await tester.pumpWidget(
MaterialApp(
home: Directionality(
textDirection: TextDirection.rtl,
child: Center(
child: FlatButton(
visualDensity: visualDensity,
key: key,
onPressed: () {},
child: useText ? const Text('Text') : Container(width: 100, height: 100, color: const Color(0xffff0000)),
),
),
),
),
);
}
await buildTest(const VisualDensity());
final RenderBox box = tester.renderObject(find.byKey(key));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(132, 100)));
await buildTest(const VisualDensity(horizontal: 3.0, vertical: 3.0));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(156, 124)));
await buildTest(const VisualDensity(horizontal: -3.0, vertical: -3.0));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(108, 100)));
await buildTest(const VisualDensity(), useText: true);
await tester.pumpAndSettle();
expect(box.size, equals(const Size(88, 48)));
await buildTest(const VisualDensity(horizontal: 3.0, vertical: 3.0), useText: true);
await tester.pumpAndSettle();
expect(box.size, equals(const Size(112, 60)));
await buildTest(const VisualDensity(horizontal: -3.0, vertical: -3.0), useText: true);
await tester.pumpAndSettle();
expect(box.size, equals(const Size(76, 36)));
});
} }
TextStyle _iconStyle(WidgetTester tester, IconData icon) { TextStyle _iconStyle(WidgetTester tester, IconData icon) {
......
...@@ -728,4 +728,51 @@ void main() { ...@@ -728,4 +728,51 @@ void main() {
); );
expect(tester.widget<Material>(rawButtonMaterial).shape, const StadiumBorder()); expect(tester.widget<Material>(rawButtonMaterial).shape, const StadiumBorder());
}); });
testWidgets('MaterialButton responds to density changes.', (WidgetTester tester) async {
const Key key = Key('test');
Future<void> buildTest(VisualDensity visualDensity, {bool useText = false}) async {
return await tester.pumpWidget(
MaterialApp(
home: Directionality(
textDirection: TextDirection.rtl,
child: Center(
child: MaterialButton(
visualDensity: visualDensity,
key: key,
onPressed: () {},
child: useText ? const Text('Text') : Container(width: 100, height: 100, color: const Color(0xffff0000)),
),
),
),
),
);
}
await buildTest(const VisualDensity());
final RenderBox box = tester.renderObject(find.byKey(key));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(132, 100)));
await buildTest(const VisualDensity(horizontal: 3.0, vertical: 3.0));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(156, 124)));
await buildTest(const VisualDensity(horizontal: -3.0, vertical: -3.0));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(108, 100)));
await buildTest(const VisualDensity(), useText: true);
await tester.pumpAndSettle();
expect(box.size, equals(const Size(88, 48)));
await buildTest(const VisualDensity(horizontal: 3.0, vertical: 3.0), useText: true);
await tester.pumpAndSettle();
expect(box.size, equals(const Size(112, 60)));
await buildTest(const VisualDensity(horizontal: -3.0, vertical: -3.0), useText: true);
await tester.pumpAndSettle();
expect(box.size, equals(const Size(76, 36)));
});
} }
...@@ -978,6 +978,53 @@ void main() { ...@@ -978,6 +978,53 @@ void main() {
await tester.longPress(outlineButton); await tester.longPress(outlineButton);
expect(didLongPressButton, isTrue); expect(didLongPressButton, isTrue);
}); });
testWidgets('OutlineButton responds to density changes.', (WidgetTester tester) async {
const Key key = Key('test');
Future<void> buildTest(VisualDensity visualDensity, {bool useText = false}) async {
return await tester.pumpWidget(
MaterialApp(
home: Directionality(
textDirection: TextDirection.rtl,
child: Center(
child: OutlineButton(
visualDensity: visualDensity,
key: key,
onPressed: () {},
child: useText ? const Text('Text') : Container(width: 100, height: 100, color: const Color(0xffff0000)),
),
),
),
),
);
}
await buildTest(const VisualDensity());
final RenderBox box = tester.renderObject(find.byKey(key));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(132, 100)));
await buildTest(const VisualDensity(horizontal: 3.0, vertical: 3.0));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(156, 124)));
await buildTest(const VisualDensity(horizontal: -3.0, vertical: -3.0));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(108, 100)));
await buildTest(const VisualDensity(), useText: true);
await tester.pumpAndSettle();
expect(box.size, equals(const Size(88, 48)));
await buildTest(const VisualDensity(horizontal: 3.0, vertical: 3.0), useText: true);
await tester.pumpAndSettle();
expect(box.size, equals(const Size(112, 60)));
await buildTest(const VisualDensity(horizontal: -3.0, vertical: -3.0), useText: true);
await tester.pumpAndSettle();
expect(box.size, equals(const Size(76, 36)));
});
} }
PhysicalModelLayer _findPhysicalLayer(Element element) { PhysicalModelLayer _findPhysicalLayer(Element element) {
......
...@@ -557,6 +557,53 @@ void main() { ...@@ -557,6 +557,53 @@ void main() {
paintsExactlyCountTimes(#clipPath, 0), paintsExactlyCountTimes(#clipPath, 0),
); );
}); });
testWidgets('RaisedButton responds to density changes.', (WidgetTester tester) async {
const Key key = Key('test');
Future<void> buildTest(VisualDensity visualDensity, {bool useText = false}) async {
return await tester.pumpWidget(
MaterialApp(
home: Directionality(
textDirection: TextDirection.rtl,
child: Center(
child: RaisedButton(
visualDensity: visualDensity,
key: key,
onPressed: () {},
child: useText ? const Text('Text') : Container(width: 100, height: 100, color: const Color(0xffff0000)),
),
),
),
),
);
}
await buildTest(const VisualDensity());
final RenderBox box = tester.renderObject(find.byKey(key));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(132, 100)));
await buildTest(const VisualDensity(horizontal: 3.0, vertical: 3.0));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(156, 124)));
await buildTest(const VisualDensity(horizontal: -3.0, vertical: -3.0));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(108, 100)));
await buildTest(const VisualDensity(), useText: true);
await tester.pumpAndSettle();
expect(box.size, equals(const Size(88, 48)));
await buildTest(const VisualDensity(horizontal: 3.0, vertical: 3.0), useText: true);
await tester.pumpAndSettle();
expect(box.size, equals(const Size(112, 60)));
await buildTest(const VisualDensity(horizontal: -3.0, vertical: -3.0), useText: true);
await tester.pumpAndSettle();
expect(box.size, equals(const Size(76, 36)));
});
} }
TextStyle _iconStyle(WidgetTester tester, IconData icon) { TextStyle _iconStyle(WidgetTester tester, IconData icon) {
......
...@@ -286,7 +286,7 @@ void main() { ...@@ -286,7 +286,7 @@ void main() {
expect(find.byKey(key).hitTestable(), findsOneWidget); expect(find.byKey(key).hitTestable(), findsOneWidget);
}); });
testWidgets('$RawMaterialButton can be expanded by parent constraints', (WidgetTester tester) async { testWidgets('RawMaterialButton can be expanded by parent constraints', (WidgetTester tester) async {
const Key key = Key('test'); const Key key = Key('test');
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -306,7 +306,7 @@ void main() { ...@@ -306,7 +306,7 @@ void main() {
expect(tester.getSize(find.byKey(key)), const Size(800.0, 48.0)); expect(tester.getSize(find.byKey(key)), const Size(800.0, 48.0));
}); });
testWidgets('$RawMaterialButton handles focus', (WidgetTester tester) async { testWidgets('RawMaterialButton handles focus', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(debugLabel: 'Button Focus'); final FocusNode focusNode = FocusNode(debugLabel: 'Button Focus');
const Key key = Key('test'); const Key key = Key('test');
const Color focusColor = Color(0xff00ff00); const Color focusColor = Color(0xff00ff00);
...@@ -334,7 +334,7 @@ void main() { ...@@ -334,7 +334,7 @@ void main() {
expect(box, paints..rect(color: focusColor)); expect(box, paints..rect(color: focusColor));
}); });
testWidgets('$RawMaterialButton loses focus when disabled.', (WidgetTester tester) async { testWidgets('RawMaterialButton loses focus when disabled.', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(debugLabel: 'RawMaterialButton'); final FocusNode focusNode = FocusNode(debugLabel: 'RawMaterialButton');
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -368,7 +368,7 @@ void main() { ...@@ -368,7 +368,7 @@ void main() {
expect(focusNode.hasPrimaryFocus, isFalse); expect(focusNode.hasPrimaryFocus, isFalse);
}); });
testWidgets("Disabled $RawMaterialButton can't be traversed to when disabled.", (WidgetTester tester) async { testWidgets("Disabled RawMaterialButton can't be traversed to when disabled.", (WidgetTester tester) async {
final FocusNode focusNode1 = FocusNode(debugLabel: '$RawMaterialButton 1'); final FocusNode focusNode1 = FocusNode(debugLabel: '$RawMaterialButton 1');
final FocusNode focusNode2 = FocusNode(debugLabel: '$RawMaterialButton 2'); final FocusNode focusNode2 = FocusNode(debugLabel: '$RawMaterialButton 2');
...@@ -406,7 +406,7 @@ void main() { ...@@ -406,7 +406,7 @@ void main() {
expect(focusNode2.hasPrimaryFocus, isFalse); expect(focusNode2.hasPrimaryFocus, isFalse);
}); });
testWidgets('$RawMaterialButton handles hover', (WidgetTester tester) async { testWidgets('RawMaterialButton handles hover', (WidgetTester tester) async {
const Key key = Key('test'); const Key key = Key('test');
const Color hoverColor = Color(0xff00ff00); const Color hoverColor = Color(0xff00ff00);
...@@ -510,4 +510,51 @@ void main() { ...@@ -510,4 +510,51 @@ void main() {
await tester.longPress(rawMaterialButton); await tester.longPress(rawMaterialButton);
expect(didLongPressButton, isTrue); expect(didLongPressButton, isTrue);
}); });
testWidgets('RawMaterialButton responds to density changes.', (WidgetTester tester) async {
const Key key = Key('test');
Future<void> buildTest(VisualDensity visualDensity, {bool useText = false}) async {
return await tester.pumpWidget(
MaterialApp(
home: Directionality(
textDirection: TextDirection.rtl,
child: Center(
child: RawMaterialButton(
visualDensity: visualDensity,
key: key,
onPressed: () {},
child: useText ? const Text('Text') : Container(width: 100, height: 100, color: const Color(0xffff0000)),
),
),
),
),
);
}
await buildTest(const VisualDensity());
final RenderBox box = tester.renderObject(find.byKey(key));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(100, 100)));
await buildTest(const VisualDensity(horizontal: 3.0, vertical: 3.0));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(124, 124)));
await buildTest(const VisualDensity(horizontal: -3.0, vertical: -3.0));
await tester.pumpAndSettle();
expect(box.size, equals(const Size(100, 100)));
await buildTest(const VisualDensity(), useText: true);
await tester.pumpAndSettle();
expect(box.size, equals(const Size(88, 48)));
await buildTest(const VisualDensity(horizontal: 3.0, vertical: 3.0), useText: true);
await tester.pumpAndSettle();
expect(box.size, equals(const Size(100, 60)));
await buildTest(const VisualDensity(horizontal: -3.0, vertical: -3.0), useText: true);
await tester.pumpAndSettle();
expect(box.size, equals(const Size(76, 36)));
});
} }
...@@ -201,6 +201,7 @@ void main() { ...@@ -201,6 +201,7 @@ void main() {
final ThemeData theme = ThemeData.raw( final ThemeData theme = ThemeData.raw(
brightness: Brightness.dark, brightness: Brightness.dark,
visualDensity: const VisualDensity(),
primaryColor: Colors.black, primaryColor: Colors.black,
primaryColorBrightness: Brightness.dark, primaryColorBrightness: Brightness.dark,
primaryColorLight: Colors.black, primaryColorLight: Colors.black,
...@@ -279,6 +280,7 @@ void main() { ...@@ -279,6 +280,7 @@ void main() {
final ThemeData otherTheme = ThemeData.raw( final ThemeData otherTheme = ThemeData.raw(
brightness: Brightness.light, brightness: Brightness.light,
visualDensity: const VisualDensity(),
primaryColor: Colors.white, primaryColor: Colors.white,
primaryColorBrightness: Brightness.light, primaryColorBrightness: Brightness.light,
primaryColorLight: Colors.white, primaryColorLight: Colors.white,
......
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