flat_button.dart 10.6 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/rendering.dart';
7
import 'package:flutter/widgets.dart';
8

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

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

  /// 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.
  ///
177
  /// The [icon], [label], and [clipBehavior] arguments must not be null.
178
  factory FlatButton.icon({
179
    Key key,
180
    required VoidCallback onPressed,
181
    VoidCallback onLongPress,
182
    ValueChanged<bool> onHighlightChanged,
183
    MouseCursor mouseCursor,
184 185 186 187 188
    ButtonTextTheme textTheme,
    Color textColor,
    Color disabledTextColor,
    Color color,
    Color disabledColor,
189 190
    Color focusColor,
    Color hoverColor,
191 192 193 194 195 196
    Color highlightColor,
    Color splashColor,
    Brightness colorBrightness,
    EdgeInsetsGeometry padding,
    ShapeBorder shape,
    Clip clipBehavior,
197
    FocusNode focusNode,
198
    bool autofocus,
199
    MaterialTapTargetSize materialTapTargetSize,
200 201
    required Widget icon,
    required Widget label,
202 203
    double minWidth,
    double height,
204
  }) = _FlatButtonWithIcon;
205

206
  @override
207
  Widget build(BuildContext context) {
208
    final ThemeData theme = Theme.of(context)!;
209
    final ButtonThemeData buttonTheme = ButtonTheme.of(context);
210
    return RawMaterialButton(
211
      onPressed: onPressed,
212
      onLongPress: onLongPress,
213
      onHighlightChanged: onHighlightChanged,
214
      mouseCursor: mouseCursor,
215
      fillColor: buttonTheme.getFillColor(this),
216
      textStyle: theme.textTheme.button!.copyWith(color: buttonTheme.getTextColor(this)),
217 218
      focusColor: buttonTheme.getFocusColor(this),
      hoverColor: buttonTheme.getHoverColor(this),
219 220 221
      highlightColor: buttonTheme.getHighlightColor(this),
      splashColor: buttonTheme.getSplashColor(this),
      elevation: buttonTheme.getElevation(this),
222 223
      focusElevation: buttonTheme.getFocusElevation(this),
      hoverElevation: buttonTheme.getHoverElevation(this),
224 225 226
      highlightElevation: buttonTheme.getHighlightElevation(this),
      disabledElevation: buttonTheme.getDisabledElevation(this),
      padding: buttonTheme.getPadding(this),
227
      visualDensity: visualDensity ?? theme.visualDensity,
228 229 230 231
      constraints: buttonTheme.getConstraints(this).copyWith(
        minWidth: minWidth,
        minHeight: height,
      ),
232
      shape: buttonTheme.getShape(this),
233
      clipBehavior: clipBehavior,
234
      focusNode: focusNode,
235
      autofocus: autofocus,
236
      materialTapTargetSize: buttonTheme.getMaterialTapTargetSize(this),
237
      animationDuration: buttonTheme.getAnimationDuration(this),
238
      child: child,
239
    );
240 241
  }
}
242

Shi-Hao Hong's avatar
Shi-Hao Hong committed
243
/// The type of FlatButtons created with [FlatButton.icon].
244 245 246
///
/// This class only exists to give FlatButtons created with [FlatButton.icon]
/// a distinct class for the sake of [ButtonTheme]. It can not be instantiated.
247
class _FlatButtonWithIcon extends FlatButton with MaterialButtonWithIconMixin {
248
  _FlatButtonWithIcon({
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
    Key? key,
    required VoidCallback? onPressed,
    VoidCallback? onLongPress,
    ValueChanged<bool>? onHighlightChanged,
    MouseCursor? mouseCursor,
    ButtonTextTheme? textTheme,
    Color? textColor,
    Color? disabledTextColor,
    Color? color,
    Color? disabledColor,
    Color? focusColor,
    Color? hoverColor,
    Color? highlightColor,
    Color? splashColor,
    Brightness? colorBrightness,
    EdgeInsetsGeometry? padding,
    ShapeBorder? shape,
266
    Clip clipBehavior = Clip.none,
267
    FocusNode? focusNode,
268
    bool autofocus = false,
269 270 271 272 273
    MaterialTapTargetSize? materialTapTargetSize,
    required Widget icon,
    required Widget label,
    double? minWidth,
    double? height,
274 275
  }) : assert(icon != null),
       assert(label != null),
276
       assert(clipBehavior != null),
277
       assert(autofocus != null),
278 279 280
       super(
         key: key,
         onPressed: onPressed,
281
         onLongPress: onLongPress,
282
         onHighlightChanged: onHighlightChanged,
283
         mouseCursor: mouseCursor,
284 285 286 287 288
         textTheme: textTheme,
         textColor: textColor,
         disabledTextColor: disabledTextColor,
         color: color,
         disabledColor: disabledColor,
289 290
         focusColor: focusColor,
         hoverColor: hoverColor,
291 292 293 294 295 296
         highlightColor: highlightColor,
         splashColor: splashColor,
         colorBrightness: colorBrightness,
         padding: padding,
         shape: shape,
         clipBehavior: clipBehavior,
297
         focusNode: focusNode,
298
         autofocus: autofocus,
299 300 301 302 303 304 305 306 307
         materialTapTargetSize: materialTapTargetSize,
         child: Row(
           mainAxisSize: MainAxisSize.min,
           children: <Widget>[
             icon,
             const SizedBox(width: 8.0),
             label,
           ],
         ),
308 309
         minWidth: minWidth,
         height: height,
310 311 312
       );

}