Commit 25ac924e authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Modify the MaterialButton to expand when text is scaled. (#12431)

This modifies the MaterialButton to expand vertically to fit the size of the contained child, no matter what the child widget is. It tries to be as close as possible to the minHeight constraint.

Also updated some doc comments to have headers (extra blank line after first sentence), and to wrap at 80 cols.

Addresses #12311
parent 6c6d08b9
......@@ -504,19 +504,18 @@ class RenderBoxToRenderSectorAdapter extends RenderBox with RenderObjectWithChil
@override
void performLayout() {
if (child == null) {
if (child == null || (!constraints.hasBoundedWidth && !constraints.hasBoundedHeight)) {
size = constraints.constrain(Size.zero);
} else {
assert(child is RenderSector);
assert(constraints.maxWidth < double.INFINITY || constraints.maxHeight < double.INFINITY);
final double maxChildDeltaRadius = math.min(constraints.maxWidth, constraints.maxHeight) / 2.0 - innerRadius;
assert(child.parentData is SectorParentData);
child.parentData.radius = innerRadius;
child.parentData.theta = 0.0;
child.layout(new SectorConstraints(maxDeltaRadius: maxChildDeltaRadius), parentUsesSize: true);
final double dimension = (innerRadius + child.deltaRadius) * 2.0;
size = constraints.constrain(new Size(dimension, dimension));
return;
}
assert(child is RenderSector);
assert(child.parentData is SectorParentData);
final double maxChildDeltaRadius = math.min(constraints.maxWidth, constraints.maxHeight) / 2.0 - innerRadius;
child.parentData.radius = innerRadius;
child.parentData.theta = 0.0;
child.layout(new SectorConstraints(maxDeltaRadius: maxChildDeltaRadius), parentUsesSize: true);
final double dimension = (innerRadius + child.deltaRadius) * 2.0;
size = constraints.constrain(new Size(dimension, dimension));
}
@override
......
......@@ -22,10 +22,12 @@ import 'theme.dart';
/// * [RaisedButton], which styles itself based on the ambient [ButtonTheme].
/// * [FlatButton], which styles itself based on the ambient [ButtonTheme].
enum ButtonTextTheme {
/// The button should use the normal color (e.g., black or white depending on the [ThemeData.brightness]) for its text.
/// The button should use the normal color (e.g., black or white depending on
/// the [ThemeData.brightness]) for its text.
normal,
/// The button should use the accent color (e.g., [ThemeData.accentColor]) for its text.
/// The button should use the accent color (e.g., [ThemeData.accentColor]) for
/// its text.
accent,
}
......@@ -123,6 +125,8 @@ class ButtonTheme extends InheritedWidget {
/// If you want an ink-splash effect for taps, but don't want to use a button,
/// consider using [InkWell] directly.
///
/// The button will expand to fit the child widget, if necessary.
///
/// See also:
///
/// * [IconButton], to create buttons that contain icons rather than text.
......@@ -177,20 +181,26 @@ class MaterialButton extends StatefulWidget {
/// ```
final Color color;
/// The primary color of the button when the button is in the down (pressed) state.
/// The primary color of the button when the button is in the down (pressed)
/// state.
///
/// The splash is represented as a circular overlay that appears above the
/// [highlightColor] overlay. The splash overlay has a center point that matches
/// the hit point of the user touch event. The splash overlay will expand to
/// fill the button area if the touch is held for long enough time. If the splash
/// color has transparency then the highlight and button color will show through.
/// [highlightColor] overlay. The splash overlay has a center point that
/// matches the hit point of the user touch event. The splash overlay will
/// expand to fill the button area if the touch is held for long enough time.
/// If the splash color has transparency then the highlight and button color
/// will show through.
///
/// Defaults to the Theme's splash color, [ThemeData.splashColor].
final Color splashColor;
/// The secondary color of the button when the button is in the down (pressed)
/// state. The higlight color is represented as a solid color that is overlaid over the
/// button color (if any). If the highlight color has transparency, the button color
/// will show through. The highlight fades in quickly as the button is held down.
/// state.
///
/// The highlight color is represented as a solid color that is overlaid over
/// the button color (if any). If the highlight color has transparency, the
/// button color will show through. The highlight fades in quickly as the
/// button is held down.
///
/// Defaults to the Theme's highlight color, [ThemeData.highlightColor].
final Color highlightColor;
......@@ -319,6 +329,7 @@ class _MaterialButtonState extends State<MaterialButton> {
padding: widget.padding ?? ButtonTheme.of(context).padding,
child: new Center(
widthFactor: 1.0,
heightFactor: 1.0,
child: widget.child
)
)
......@@ -343,7 +354,6 @@ class _MaterialButtonState extends State<MaterialButton> {
constraints: new BoxConstraints(
minWidth: widget.minWidth ?? buttonTheme.minWidth,
minHeight: height,
maxHeight: height
),
child: contents
);
......
......@@ -34,6 +34,8 @@ import 'theme.dart';
///
/// Requires one of its ancestors to be a [Material] widget.
///
/// Flat buttons will expand to fit the child widget, if necessary.
///
/// See also:
///
/// * [RaisedButton], which is a button that hovers above the containing
......@@ -63,7 +65,8 @@ class FlatButton extends StatelessWidget {
}) : assert(child != null),
super(key: key);
/// The callback that is called when the button is tapped or otherwise activated.
/// The callback that is called when the button is tapped or otherwise
/// activated.
///
/// If this is set to null, the button will be disabled.
final VoidCallback onPressed;
......@@ -81,7 +84,8 @@ class FlatButton extends StatelessWidget {
/// The primary color of the button, as printed on the [Material], while it
/// is in its default (unpressed, enabled) state.
///
/// Defaults to null, meaning that the color is automatically derived from the [Theme].
/// Defaults to null, meaning that the color is automatically derived from the
/// [Theme].
///
/// Typically, a material design color will be used, as follows:
///
......@@ -94,27 +98,34 @@ class FlatButton extends StatelessWidget {
/// ```
final Color color;
/// The primary color of the button when the button is in the down (pressed) state.
/// The primary color of the button when the button is in the down (pressed)
/// state.
///
/// The splash is represented as a circular overlay that appears above the
/// [highlightColor] overlay. The splash overlay has a center point that matches
/// the hit point of the user touch event. The splash overlay will expand to
/// fill the button area if the touch is held for long enough time. If the splash
/// color has transparency then the highlight and button color will show through.
/// [highlightColor] overlay. The splash overlay has a center point that
/// matches the hit point of the user touch event. The splash overlay will
/// expand to fill the button area if the touch is held for long enough time.
/// If the splash color has transparency then the highlight and button color
/// will show through.
///
/// Defaults to the Theme's splash color, [ThemeData.splashColor].
final Color splashColor;
/// The secondary color of the button when the button is in the down (pressed)
/// state. The higlight color is represented as a solid color that is overlaid over the
/// button color (if any). If the highlight color has transparency, the button color
/// will show through. The highlight fades in quickly as the button is held down.
/// state.
///
/// The highlight color is represented as a solid color that is overlaid over
/// the button color (if any). If the highlight color has transparency, the
/// button color will show through. The highlight fades in quickly as the
/// button is held down.
///
/// Defaults to the Theme's highlight color, [ThemeData.highlightColor].
final Color highlightColor;
/// The color of the button when the button is disabled. Buttons are disabled
/// by default. To enable a button, set its [onPressed] property to a non-null
/// value.
/// The color of the button when the button is disabled.
///
/// Buttons are disabled by default. To enable a button, set its [onPressed]
/// property to a non-null value.
final Color disabledColor;
/// The color scheme to use for this button's text.
......@@ -132,8 +143,10 @@ class FlatButton extends StatelessWidget {
/// Typically a [Text] widget in all caps.
final Widget child;
/// Whether the button is enabled or disabled. Buttons are disabled by default. To
/// enable a button, set its [onPressed] property to a non-null value.
/// Whether the button is enabled or disabled.
///
/// Buttons are disabled by default. To enable a button, set its [onPressed]
/// property to a non-null value.
bool get enabled => onPressed != null;
@override
......
......@@ -28,6 +28,8 @@ import 'theme.dart';
/// If you want an ink-splash effect for taps, but don't want to use a button,
/// consider using [InkWell] directly.
///
/// Raised buttons will expand to fit the child widget, if necessary.
///
/// See also:
///
/// * [FlatButton], a material design button without a shadow.
......@@ -55,7 +57,8 @@ class RaisedButton extends StatelessWidget {
this.child
}) : super(key: key);
/// The callback that is called when the button is tapped or otherwise activated.
/// The callback that is called when the button is tapped or otherwise
/// activated.
///
/// If this is set to null, the button will be disabled.
final VoidCallback onPressed;
......@@ -63,7 +66,8 @@ class RaisedButton extends StatelessWidget {
/// The primary color of the button, as printed on the [Material], while it
/// is in its default (unpressed, enabled) state.
///
/// Defaults to null, meaning that the color is automatically derived from the [Theme].
/// Defaults to null, meaning that the color is automatically derived from the
/// [Theme].
///
/// Typically, a material design color will be used, as follows:
///
......@@ -76,28 +80,35 @@ class RaisedButton extends StatelessWidget {
/// ```
final Color color;
/// The primary color of the button when the button is in the down (pressed) state.
/// The primary color of the button when the button is in the down (pressed)
/// state.
///
/// The splash is represented as a circular overlay that appears above the
/// [highlightColor] overlay. The splash overlay has a center point that matches
/// the hit point of the user touch event. The splash overlay will expand to
/// fill the button area if the touch is held for long enough time. If the splash
/// color has transparency then the highlight and button color will show through.
/// [highlightColor] overlay. The splash overlay has a center point that
/// matches the hit point of the user touch event. The splash overlay will
/// expand to fill the button area if the touch is held for long enough time.
/// If the splash color has transparency then the highlight and button color
/// will show through.
///
/// Defaults to the splash color from the [Theme].
final Color splashColor;
/// The secondary color of the button when the button is in the down (pressed)
/// state. The higlight color is represented as a solid color that is overlaid over the
/// button color (if any). If the highlight color has transparency, the button color
/// will show through. The highlight fades in quickly as the button is held down.
/// state.
///
/// The highlight color is represented as a solid color that is overlaid over
/// the button color (if any). If the highlight color has transparency, the
/// button color will show through. The highlight fades in quickly as the
/// button is held down.
///
/// Defaults to the highlight color from the [Theme].
final Color highlightColor;
/// The color of the button when the button is disabled. Buttons are disabled
/// by default. To enable a button, set its [onPressed] property to a non-null
/// value.
/// by default.
///
/// To enable a button, set its [onPressed] property to a non-null value.
final Color disabledColor;
/// The z-coordinate at which to place this button. This controls the size of
......@@ -141,8 +152,10 @@ class RaisedButton extends StatelessWidget {
/// Typically a [Text] widget in all caps.
final Widget child;
/// Whether the button is enabled or disabled. Buttons are disabled by default. To
/// enable a button, set its [onPressed] property to a non-null value.
/// Whether the button is enabled or disabled.
///
/// Buttons are disabled by default. To enable a button, set its [onPressed]
/// property to a non-null value.
bool get enabled => onPressed != null;
Color _getColor(BuildContext context) {
......
......@@ -63,7 +63,9 @@ void main() {
);
expect(tester.getSize(find.byType(FlatButton)), equals(const Size(88.0, 36.0)));
expect(tester.getSize(find.byType(Text)), equals(const Size(42.0, 14.0)));
// textScaleFactor expands text, but not button.
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr,
......@@ -82,6 +84,36 @@ void main() {
);
expect(tester.getSize(find.byType(FlatButton)), equals(const Size(88.0, 36.0)));
// Scaled text rendering is different on Linux and Mac by one pixel.
// TODO(#12357): Update this test when text rendering is fixed.
expect(tester.getSize(find.byType(Text)).width, isIn(<double>[54.0, 55.0]));
expect(tester.getSize(find.byType(Text)).height, equals(19.0));
// Set text scale large enough to expand text and button.
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr,
child: new Material(
child: new MediaQuery(
data: const MediaQueryData(textScaleFactor: 3.0),
child: new Center(
child: new FlatButton(
onPressed: () { },
child: const Text('ABC'),
),
),
),
),
),
);
// Scaled text rendering is different on Linux and Mac by one pixel.
// TODO(#12357): Update this test when text rendering is fixed.
expect(tester.getSize(find.byType(FlatButton)).width, isIn(<double>[158.0, 159.0]));
expect(tester.getSize(find.byType(FlatButton)).height, equals(42.0));
expect(tester.getSize(find.byType(Text)).width, isIn(<double>[126.0, 127.0]));
expect(tester.getSize(find.byType(Text)).height, equals(42.0));
});
// This test is very similar to the '...explicit splashColor and highlightColor' test
......
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