raised_button.dart 11.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/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 snippet --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 206
    MaterialTapTargetSize materialTapTargetSize,
    Duration animationDuration,
207 208
    @required Widget icon,
    @required Widget label,
209
  }) = _RaisedButtonWithIcon;
210

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

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

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