raised_button.dart 11.9 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 "raised button".
///
17 18
/// A raised button is based on a [Material] widget whose [Material.elevation]
/// increases when the button is pressed.
19 20 21 22 23
///
/// Use raised buttons to add dimension to otherwise mostly flat layouts, e.g.
/// in long busy lists of content, or in wide spaces. Avoid using raised buttons
/// on already-raised content such as dialogs or cards.
///
24
/// If [onPressed] and [onLongPress] callbacks are null, then the button will be disabled and by
25
/// default will resemble a flat button in the [disabledColor]. If you are
26
/// trying to change the button's [color] and it is not having any effect, check
27
/// that you are passing a non-null [onPressed] or [onLongPress] callbacks.
28
///
29 30 31
/// If you want an ink-splash effect for taps, but don't want to use a button,
/// consider using [InkWell] directly.
///
32
/// Raised buttons have a minimum size of 88.0 by 36.0 which can be overridden
33
/// with [ButtonTheme].
34
///
35
/// {@tool dartpad --template=stateless_widget_scaffold}
36 37 38 39
///
/// This sample shows how to render a disabled RaisedButton, an enabled RaisedButton
/// and lastly a RaisedButton with gradient background.
///
40 41 42
/// ![Three raised buttons, one enabled, another disabled, and the last one
/// styled with a blue gradient background](https://flutter.github.io/assets-for-api-docs/assets/material/raised_button.png)
///
43
/// ```dart
44
/// Widget build(BuildContext context) {
45 46 47 48 49 50 51 52 53
///   return Center(
///     child: Column(
///       mainAxisSize: MainAxisSize.min,
///       children: <Widget>[
///         const RaisedButton(
///           onPressed: null,
///           child: Text(
///             'Disabled Button',
///             style: TextStyle(fontSize: 20)
54
///           ),
55 56 57 58 59 60 61
///         ),
///         const SizedBox(height: 30),
///         RaisedButton(
///           onPressed: () {},
///           child: const Text(
///             'Enabled Button',
///             style: TextStyle(fontSize: 20)
62
///           ),
63 64 65 66 67 68 69 70 71 72 73 74 75 76
///         ),
///         const SizedBox(height: 30),
///         RaisedButton(
///           onPressed: () {},
///           textColor: Colors.white,
///           padding: const EdgeInsets.all(0.0),
///           child: Container(
///             decoration: const BoxDecoration(
///               gradient: LinearGradient(
///                 colors: <Color>[
///                   Color(0xFF0D47A1),
///                   Color(0xFF1976D2),
///                   Color(0xFF42A5F5),
///                 ],
77
///               ),
78 79 80 81 82
///             ),
///             padding: const EdgeInsets.all(10.0),
///             child: const Text(
///               'Gradient Button',
///               style: TextStyle(fontSize: 20)
83 84
///             ),
///           ),
85 86
///         ),
///       ],
87
///     ),
88 89
///   );
/// }
90 91 92
/// ```
/// {@end-tool}
///
93
/// See also:
94
///
95 96 97 98 99
///  * [FlatButton], a material design button without a shadow.
///  * [DropdownButton], a button that shows options to select from.
///  * [FloatingActionButton], the round button in material applications.
///  * [IconButton], to create buttons that just contain icons.
///  * [InkWell], which implements the ink splash part of a flat button.
100
///  * [RawMaterialButton], the widget this widget is based on.
101
///  * <https://material.io/design/components/buttons.html>
102
class RaisedButton extends MaterialButton {
103
  /// Create a filled button.
104
  ///
105 106 107 108
  /// The [autofocus] and [clipBehavior] arguments must not be null.
  /// Additionally,  [elevation], [hoverElevation], [focusElevation],
  /// [highlightElevation], and [disabledElevation] must be non-negative, if
  /// specified.
109
  const RaisedButton({
110
    Key key,
111
    @required VoidCallback onPressed,
112
    VoidCallback onLongPress,
113
    ValueChanged<bool> onHighlightChanged,
114
    MouseCursor mouseCursor,
115 116 117 118 119
    ButtonTextTheme textTheme,
    Color textColor,
    Color disabledTextColor,
    Color color,
    Color disabledColor,
120 121
    Color focusColor,
    Color hoverColor,
122 123 124 125
    Color highlightColor,
    Color splashColor,
    Brightness colorBrightness,
    double elevation,
126 127
    double focusElevation,
    double hoverElevation,
128 129 130
    double highlightElevation,
    double disabledElevation,
    EdgeInsetsGeometry padding,
131
    VisualDensity visualDensity,
132
    ShapeBorder shape,
133
    Clip clipBehavior = Clip.none,
134
    FocusNode focusNode,
135
    bool autofocus = false,
136 137 138
    MaterialTapTargetSize materialTapTargetSize,
    Duration animationDuration,
    Widget child,
139 140
  }) : assert(autofocus != null),
       assert(elevation == null || elevation >= 0.0),
141 142
       assert(focusElevation == null || focusElevation >= 0.0),
       assert(hoverElevation == null || hoverElevation >= 0.0),
143 144
       assert(highlightElevation == null || highlightElevation >= 0.0),
       assert(disabledElevation == null || disabledElevation >= 0.0),
145
       assert(clipBehavior != null),
146 147 148
       super(
         key: key,
         onPressed: onPressed,
149
         onLongPress: onLongPress,
150
         onHighlightChanged: onHighlightChanged,
151
         mouseCursor: mouseCursor,
152 153 154 155 156
         textTheme: textTheme,
         textColor: textColor,
         disabledTextColor: disabledTextColor,
         color: color,
         disabledColor: disabledColor,
157 158
         focusColor: focusColor,
         hoverColor: hoverColor,
159 160 161 162
         highlightColor: highlightColor,
         splashColor: splashColor,
         colorBrightness: colorBrightness,
         elevation: elevation,
163 164
         focusElevation: focusElevation,
         hoverElevation: hoverElevation,
165 166 167
         highlightElevation: highlightElevation,
         disabledElevation: disabledElevation,
         padding: padding,
168
         visualDensity: visualDensity,
169 170
         shape: shape,
         clipBehavior: clipBehavior,
171
         focusNode: focusNode,
172
         autofocus: autofocus,
173 174 175 176
         materialTapTargetSize: materialTapTargetSize,
         animationDuration: animationDuration,
         child: child,
       );
177 178 179 180 181 182 183

  /// Create a filled 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.
  ///
184 185
  /// The [elevation], [highlightElevation], [disabledElevation], [icon],
  /// [label], and [clipBehavior] arguments must not be null.
186
  factory RaisedButton.icon({
187
    Key key,
188
    @required VoidCallback onPressed,
189
    VoidCallback onLongPress,
190
    ValueChanged<bool> onHighlightChanged,
191
    MouseCursor mouseCursor,
192 193 194 195 196
    ButtonTextTheme textTheme,
    Color textColor,
    Color disabledTextColor,
    Color color,
    Color disabledColor,
197 198
    Color focusColor,
    Color hoverColor,
199 200 201 202 203 204 205 206
    Color highlightColor,
    Color splashColor,
    Brightness colorBrightness,
    double elevation,
    double highlightElevation,
    double disabledElevation,
    ShapeBorder shape,
    Clip clipBehavior,
207
    FocusNode focusNode,
208
    bool autofocus,
209
    EdgeInsetsGeometry padding,
210 211
    MaterialTapTargetSize materialTapTargetSize,
    Duration animationDuration,
212 213
    @required Widget icon,
    @required Widget label,
214
  }) = _RaisedButtonWithIcon;
215

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

  @override
250 251
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
252
    properties.add(DiagnosticsProperty<double>('elevation', elevation, defaultValue: null));
253 254
    properties.add(DiagnosticsProperty<double>('focusElevation', focusElevation, defaultValue: null));
    properties.add(DiagnosticsProperty<double>('hoverElevation', hoverElevation, defaultValue: null));
255 256
    properties.add(DiagnosticsProperty<double>('highlightElevation', highlightElevation, defaultValue: null));
    properties.add(DiagnosticsProperty<double>('disabledElevation', disabledElevation, defaultValue: null));
257
  }
258
}
259

Shi-Hao Hong's avatar
Shi-Hao Hong committed
260
/// The type of RaisedButtons created with [RaisedButton.icon].
261 262 263
///
/// This class only exists to give RaisedButtons created with [RaisedButton.icon]
/// a distinct class for the sake of [ButtonTheme]. It can not be instantiated.
264
class _RaisedButtonWithIcon extends RaisedButton with MaterialButtonWithIconMixin {
265 266 267
  _RaisedButtonWithIcon({
    Key key,
    @required VoidCallback onPressed,
268
    VoidCallback onLongPress,
269
    ValueChanged<bool> onHighlightChanged,
270
    MouseCursor mouseCursor,
271 272 273 274 275
    ButtonTextTheme textTheme,
    Color textColor,
    Color disabledTextColor,
    Color color,
    Color disabledColor,
276 277
    Color focusColor,
    Color hoverColor,
278 279 280 281 282 283 284 285
    Color highlightColor,
    Color splashColor,
    Brightness colorBrightness,
    double elevation,
    double highlightElevation,
    double disabledElevation,
    ShapeBorder shape,
    Clip clipBehavior = Clip.none,
286
    FocusNode focusNode,
287
    bool autofocus = false,
288
    EdgeInsetsGeometry padding,
289 290 291 292 293 294 295
    MaterialTapTargetSize materialTapTargetSize,
    Duration animationDuration,
    @required Widget icon,
    @required Widget label,
  }) : assert(elevation == null || elevation >= 0.0),
       assert(highlightElevation == null || highlightElevation >= 0.0),
       assert(disabledElevation == null || disabledElevation >= 0.0),
296
       assert(clipBehavior != null),
297 298
       assert(icon != null),
       assert(label != null),
299
       assert(autofocus != null),
300 301 302
       super(
         key: key,
         onPressed: onPressed,
303
         onLongPress: onLongPress,
304
         onHighlightChanged: onHighlightChanged,
305
         mouseCursor: mouseCursor,
306 307 308 309 310
         textTheme: textTheme,
         textColor: textColor,
         disabledTextColor: disabledTextColor,
         color: color,
         disabledColor: disabledColor,
311 312
         focusColor: focusColor,
         hoverColor: hoverColor,
313 314 315 316 317 318 319 320
         highlightColor: highlightColor,
         splashColor: splashColor,
         colorBrightness: colorBrightness,
         elevation: elevation,
         highlightElevation: highlightElevation,
         disabledElevation: disabledElevation,
         shape: shape,
         clipBehavior: clipBehavior,
321
         focusNode: focusNode,
322
         autofocus: autofocus,
323
         padding: padding,
324 325 326 327 328 329 330 331 332 333 334 335
         materialTapTargetSize: materialTapTargetSize,
         animationDuration: animationDuration,
         child: Row(
           mainAxisSize: MainAxisSize.min,
           children: <Widget>[
             icon,
             const SizedBox(width: 8.0),
             label,
           ],
         ),
       );
}