flat_button.dart 9.39 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
import 'package:flutter/foundation.dart';
6
import 'package:flutter/widgets.dart';
7

8
import 'button.dart';
9
import 'button_theme.dart';
10
import 'material_button.dart';
11
import 'theme.dart';
12
import 'theme_data.dart';
13

14 15
/// A material design "flat button".
///
16 17
/// A flat button is a text label displayed on a (zero elevation) [Material]
/// widget that reacts to touches by filling with color.
18 19 20 21 22 23 24 25 26
///
/// 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.
///
27 28 29 30 31
/// 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.
///
32
/// If the [onPressed] and [onLongPress] callbacks are null, then this button will be disabled,
33
/// will not react to touch, and will be colored as specified by
34 35 36 37
/// 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.
///
38
/// Flat buttons have a minimum size of 88.0 by 36.0 which can be overridden
39
/// with [ButtonTheme].
40
///
41 42
/// The [clipBehavior] argument must not be null.
///
43
/// {@tool snippet}
44 45 46
///
/// This example shows a simple [FlatButton].
///
47 48
/// ![A simple FlatButton](https://flutter.github.io/assets-for-api-docs/assets/material/flat_button.png)
///
49 50 51 52 53 54 55 56 57 58 59 60
/// ```dart
/// FlatButton(
///   onPressed: () {
///     /*...*/
///   },
///   child: Text(
///     "Flat Button",
///   ),
/// )
/// ```
/// {@end-tool}
///
61
/// {@tool snippet}
62 63 64 65 66 67
///
/// 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.
///
68 69
/// ![A FlatButton with white text on a blue background](https://flutter.github.io/assets-for-api-docs/assets/material/flat_button_properties.png)
///
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
/// ```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}
///
89
/// See also:
90
///
91
///  * [RaisedButton], a filled button whose material elevates when pressed.
92 93
///  * [DropdownButton], which offers the user a choice of a number of options.
///  * [SimpleDialogOption], which is used in [SimpleDialog]s.
94
///  * [IconButton], to create buttons that just contain icons.
95
///  * [InkWell], which implements the ink splash part of a flat button.
96
///  * [RawMaterialButton], the widget this widget is based on.
97
///  * <https://material.io/design/components/buttons.html>
98
class FlatButton extends MaterialButton {
99
  /// Create a simple text button.
100 101
  ///
  /// The [autofocus] and [clipBehavior] arguments must not be null.
102
  const FlatButton({
103
    Key key,
104
    @required VoidCallback onPressed,
105
    VoidCallback onLongPress,
106 107 108 109 110 111
    ValueChanged<bool> onHighlightChanged,
    ButtonTextTheme textTheme,
    Color textColor,
    Color disabledTextColor,
    Color color,
    Color disabledColor,
112 113
    Color focusColor,
    Color hoverColor,
114 115 116 117
    Color highlightColor,
    Color splashColor,
    Brightness colorBrightness,
    EdgeInsetsGeometry padding,
118
    VisualDensity visualDensity,
119
    ShapeBorder shape,
120
    Clip clipBehavior = Clip.none,
121
    FocusNode focusNode,
122
    bool autofocus = false,
123 124
    MaterialTapTargetSize materialTapTargetSize,
    @required Widget child,
125 126
  }) : assert(clipBehavior != null),
       assert(autofocus != null),
127
       super(
128 129
         key: key,
         onPressed: onPressed,
130
         onLongPress: onLongPress,
131 132 133 134 135 136
         onHighlightChanged: onHighlightChanged,
         textTheme: textTheme,
         textColor: textColor,
         disabledTextColor: disabledTextColor,
         color: color,
         disabledColor: disabledColor,
137 138
         focusColor: focusColor,
         hoverColor: hoverColor,
139 140 141 142
         highlightColor: highlightColor,
         splashColor: splashColor,
         colorBrightness: colorBrightness,
         padding: padding,
143
         visualDensity: visualDensity,
144 145
         shape: shape,
         clipBehavior: clipBehavior,
146
         focusNode: focusNode,
147
         autofocus: autofocus,
148 149 150
         materialTapTargetSize: materialTapTargetSize,
         child: child,
      );
151 152 153 154 155 156 157

  /// 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.
  ///
158
  /// The [icon], [label], and [clipBehavior] arguments must not be null.
159
  factory FlatButton.icon({
160
    Key key,
161
    @required VoidCallback onPressed,
162
    VoidCallback onLongPress,
163 164 165 166 167 168
    ValueChanged<bool> onHighlightChanged,
    ButtonTextTheme textTheme,
    Color textColor,
    Color disabledTextColor,
    Color color,
    Color disabledColor,
169 170
    Color focusColor,
    Color hoverColor,
171 172 173 174 175 176
    Color highlightColor,
    Color splashColor,
    Brightness colorBrightness,
    EdgeInsetsGeometry padding,
    ShapeBorder shape,
    Clip clipBehavior,
177
    FocusNode focusNode,
178
    bool autofocus,
179
    MaterialTapTargetSize materialTapTargetSize,
180 181
    @required Widget icon,
    @required Widget label,
182
  }) = _FlatButtonWithIcon;
183

184
  @override
185
  Widget build(BuildContext context) {
186 187
    final ThemeData theme = Theme.of(context);
    final ButtonThemeData buttonTheme = ButtonTheme.of(context);
188
    return RawMaterialButton(
189
      onPressed: onPressed,
190
      onLongPress: onLongPress,
191
      onHighlightChanged: onHighlightChanged,
192 193
      fillColor: buttonTheme.getFillColor(this),
      textStyle: theme.textTheme.button.copyWith(color: buttonTheme.getTextColor(this)),
194 195
      focusColor: buttonTheme.getFocusColor(this),
      hoverColor: buttonTheme.getHoverColor(this),
196 197 198
      highlightColor: buttonTheme.getHighlightColor(this),
      splashColor: buttonTheme.getSplashColor(this),
      elevation: buttonTheme.getElevation(this),
199 200
      focusElevation: buttonTheme.getFocusElevation(this),
      hoverElevation: buttonTheme.getHoverElevation(this),
201 202 203
      highlightElevation: buttonTheme.getHighlightElevation(this),
      disabledElevation: buttonTheme.getDisabledElevation(this),
      padding: buttonTheme.getPadding(this),
204
      visualDensity: visualDensity ?? theme.visualDensity,
205 206
      constraints: buttonTheme.getConstraints(this),
      shape: buttonTheme.getShape(this),
207
      clipBehavior: clipBehavior,
208
      focusNode: focusNode,
209
      autofocus: autofocus,
210
      materialTapTargetSize: buttonTheme.getMaterialTapTargetSize(this),
211
      animationDuration: buttonTheme.getAnimationDuration(this),
212
      child: child,
213
    );
214 215
  }
}
216

Shi-Hao Hong's avatar
Shi-Hao Hong committed
217
/// The type of FlatButtons created with [FlatButton.icon].
218 219 220
///
/// This class only exists to give FlatButtons created with [FlatButton.icon]
/// a distinct class for the sake of [ButtonTheme]. It can not be instantiated.
221
class _FlatButtonWithIcon extends FlatButton with MaterialButtonWithIconMixin {
222 223 224
  _FlatButtonWithIcon({
    Key key,
    @required VoidCallback onPressed,
225
    VoidCallback onLongPress,
226 227 228 229 230 231
    ValueChanged<bool> onHighlightChanged,
    ButtonTextTheme textTheme,
    Color textColor,
    Color disabledTextColor,
    Color color,
    Color disabledColor,
232 233
    Color focusColor,
    Color hoverColor,
234 235 236 237 238
    Color highlightColor,
    Color splashColor,
    Brightness colorBrightness,
    EdgeInsetsGeometry padding,
    ShapeBorder shape,
239
    Clip clipBehavior = Clip.none,
240
    FocusNode focusNode,
241
    bool autofocus = false,
242 243 244 245 246
    MaterialTapTargetSize materialTapTargetSize,
    @required Widget icon,
    @required Widget label,
  }) : assert(icon != null),
       assert(label != null),
247
       assert(clipBehavior != null),
248
       assert(autofocus != null),
249 250 251
       super(
         key: key,
         onPressed: onPressed,
252
         onLongPress: onLongPress,
253 254 255 256 257 258
         onHighlightChanged: onHighlightChanged,
         textTheme: textTheme,
         textColor: textColor,
         disabledTextColor: disabledTextColor,
         color: color,
         disabledColor: disabledColor,
259 260
         focusColor: focusColor,
         hoverColor: hoverColor,
261 262 263 264 265 266
         highlightColor: highlightColor,
         splashColor: splashColor,
         colorBrightness: colorBrightness,
         padding: padding,
         shape: shape,
         clipBehavior: clipBehavior,
267
         focusNode: focusNode,
268
         autofocus: autofocus,
269 270 271 272 273 274 275 276 277 278 279 280
         materialTapTargetSize: materialTapTargetSize,
         child: Row(
           mainAxisSize: MainAxisSize.min,
           children: <Widget>[
             icon,
             const SizedBox(width: 8.0),
             label,
           ],
         ),
       );

}