blob: 5bb3fb61ecd3d63550765c6b5429c87fb4f6ca4f [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'button.dart';
import 'button_theme.dart';
import 'material_button.dart';
import 'theme.dart';
import 'theme_data.dart';
/// A material design "flat button".
///
/// A flat button is a text label displayed on a (zero elevation) [Material]
/// widget that reacts to touches by filling with color.
///
/// Use flat buttons on toolbars, in dialogs, or inline with other content but
/// offset from that content with padding so that the button's presence is
/// obvious. Flat buttons intentionally do not have visible borders and must
/// therefore rely on their position relative to other content for context. In
/// dialogs and cards, they should be grouped together in one of the bottom
/// corners. Avoid using flat buttons where they would blend in with other
/// content, for example in the middle of lists.
///
/// Material design flat buttons have an all-caps label, some internal padding,
/// and some defined dimensions. To have a part of your application be
/// interactive, with ink splashes, without also committing to these stylistic
/// choices, consider using [InkWell] instead.
///
/// If the [onPressed] callback is null, then the button will be disabled,
/// will not react to touch, and will be colored as specified by
/// the [disabledColor] property instead of the [color] property. If you are
/// trying to change the button's [color] and it is not having any effect, check
/// that you are passing a non-null [onPressed] handler.
///
/// Flat buttons have a minimum size of 88.0 by 36.0 which can be overridden
/// with [ButtonTheme].
///
/// The [clipBehavior] argument must not be null.
///
/// {@tool sample}
///
/// This example shows a simple [FlatButton].
///
/// ```dart
/// FlatButton(
/// onPressed: () {
/// /*...*/
/// },
/// child: Text(
/// "Flat Button",
/// ),
/// )
/// ```
/// {@end-tool}
///
/// {@tool sample}
///
/// This example shows a [FlatButton] that is normally white-on-blue,
/// with splashes rendered in a different shade of blue.
/// It turns black-on-grey when disabled.
/// The button has 8px of padding on each side, and the text is 20px high.
///
/// ```dart
/// FlatButton(
/// color: Colors.blue,
/// textColor: Colors.white,
/// disabledColor: Colors.grey,
/// disabledTextColor: Colors.black,
/// padding: EdgeInsets.all(8.0),
/// splashColor: Colors.blueAccent,
/// onPressed: () {
/// /*...*/
/// },
/// child: Text(
/// "Flat Button",
/// style: TextStyle(fontSize: 20.0),
/// ),
/// )
/// ```
/// {@end-tool}
///
/// See also:
///
/// * [RaisedButton], a filled button whose material elevates when pressed.
/// * [DropdownButton], which offers the user a choice of a number of options.
/// * [SimpleDialogOption], which is used in [SimpleDialog]s.
/// * [IconButton], to create buttons that just contain icons.
/// * [InkWell], which implements the ink splash part of a flat button.
/// * [RawMaterialButton], the widget this widget is based on.
/// * <https://material.io/design/components/buttons.html>
class FlatButton extends MaterialButton {
/// Create a simple text button.
const FlatButton({
Key key,
@required VoidCallback onPressed,
ValueChanged<bool> onHighlightChanged,
ButtonTextTheme textTheme,
Color textColor,
Color disabledTextColor,
Color color,
Color disabledColor,
Color highlightColor,
Color splashColor,
Brightness colorBrightness,
EdgeInsetsGeometry padding,
ShapeBorder shape,
Clip clipBehavior = Clip.none,
MaterialTapTargetSize materialTapTargetSize,
@required Widget child,
}) : super(
key: key,
onPressed: onPressed,
onHighlightChanged: onHighlightChanged,
textTheme: textTheme,
textColor: textColor,
disabledTextColor: disabledTextColor,
color: color,
disabledColor: disabledColor,
highlightColor: highlightColor,
splashColor: splashColor,
colorBrightness: colorBrightness,
padding: padding,
shape: shape,
clipBehavior: clipBehavior,
materialTapTargetSize: materialTapTargetSize,
child: child,
);
/// Create a text button from a pair of widgets that serve as the button's
/// [icon] and [label].
///
/// The icon and label are arranged in a row and padded by 12 logical pixels
/// at the start, and 16 at the end, with an 8 pixel gap in between.
///
/// The [icon], [label], and [clipBehavior] arguments must not be null.
factory FlatButton.icon({
Key key,
@required VoidCallback onPressed,
ValueChanged<bool> onHighlightChanged,
ButtonTextTheme textTheme,
Color textColor,
Color disabledTextColor,
Color color,
Color disabledColor,
Color highlightColor,
Color splashColor,
Brightness colorBrightness,
EdgeInsetsGeometry padding,
ShapeBorder shape,
Clip clipBehavior,
MaterialTapTargetSize materialTapTargetSize,
@required Widget icon,
@required Widget label,
}) = _FlatButtonWithIcon;
@override
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
final ButtonThemeData buttonTheme = ButtonTheme.of(context);
return RawMaterialButton(
onPressed: onPressed,
onHighlightChanged: onHighlightChanged,
clipBehavior: clipBehavior ?? Clip.none,
fillColor: buttonTheme.getFillColor(this),
textStyle: theme.textTheme.button.copyWith(color: buttonTheme.getTextColor(this)),
highlightColor: buttonTheme.getHighlightColor(this),
splashColor: buttonTheme.getSplashColor(this),
elevation: buttonTheme.getElevation(this),
highlightElevation: buttonTheme.getHighlightElevation(this),
disabledElevation: buttonTheme.getDisabledElevation(this),
padding: buttonTheme.getPadding(this),
constraints: buttonTheme.getConstraints(this),
shape: buttonTheme.getShape(this),
animationDuration: buttonTheme.getAnimationDuration(this),
materialTapTargetSize: buttonTheme.getMaterialTapTargetSize(this),
child: child,
);
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(ObjectFlagProperty<VoidCallback>('onPressed', onPressed, ifNull: 'disabled'));
properties.add(DiagnosticsProperty<ButtonTextTheme>('textTheme', textTheme, defaultValue: null));
properties.add(DiagnosticsProperty<Color>('textColor', textColor, defaultValue: null));
properties.add(DiagnosticsProperty<Color>('disabledTextColor', disabledTextColor, defaultValue: null));
properties.add(DiagnosticsProperty<Color>('color', color, defaultValue: null));
properties.add(DiagnosticsProperty<Color>('disabledColor', disabledColor, defaultValue: null));
properties.add(DiagnosticsProperty<Color>('highlightColor', highlightColor, defaultValue: null));
properties.add(DiagnosticsProperty<Color>('splashColor', splashColor, defaultValue: null));
properties.add(DiagnosticsProperty<Brightness>('colorBrightness', colorBrightness, defaultValue: null));
properties.add(DiagnosticsProperty<EdgeInsetsGeometry>('padding', padding, defaultValue: null));
properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null));
properties.add(DiagnosticsProperty<MaterialTapTargetSize>('materialTapTargetSize', materialTapTargetSize, defaultValue: null));
}
}
/// The type of of FlatButtons created with [FlatButton.icon].
///
/// This class only exists to give FlatButtons created with [FlatButton.icon]
/// a distinct class for the sake of [ButtonTheme]. It can not be instantiated.
class _FlatButtonWithIcon extends FlatButton with MaterialButtonWithIconMixin {
_FlatButtonWithIcon({
Key key,
@required VoidCallback onPressed,
ValueChanged<bool> onHighlightChanged,
ButtonTextTheme textTheme,
Color textColor,
Color disabledTextColor,
Color color,
Color disabledColor,
Color highlightColor,
Color splashColor,
Brightness colorBrightness,
EdgeInsetsGeometry padding,
ShapeBorder shape,
Clip clipBehavior,
MaterialTapTargetSize materialTapTargetSize,
@required Widget icon,
@required Widget label,
}) : assert(icon != null),
assert(label != null),
super(
key: key,
onPressed: onPressed,
onHighlightChanged: onHighlightChanged,
textTheme: textTheme,
textColor: textColor,
disabledTextColor: disabledTextColor,
color: color,
disabledColor: disabledColor,
highlightColor: highlightColor,
splashColor: splashColor,
colorBrightness: colorBrightness,
padding: padding,
shape: shape,
clipBehavior: clipBehavior,
materialTapTargetSize: materialTapTargetSize,
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
icon,
const SizedBox(width: 8.0),
label,
],
),
);
}