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

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

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

  @override
245 246
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
247
    properties.add(DiagnosticsProperty<double>('elevation', elevation, defaultValue: null));
248 249
    properties.add(DiagnosticsProperty<double>('focusElevation', focusElevation, defaultValue: null));
    properties.add(DiagnosticsProperty<double>('hoverElevation', hoverElevation, defaultValue: null));
250 251
    properties.add(DiagnosticsProperty<double>('highlightElevation', highlightElevation, defaultValue: null));
    properties.add(DiagnosticsProperty<double>('disabledElevation', disabledElevation, defaultValue: null));
252
  }
253
}
254

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