raised_button.dart 11.5 KB
Newer Older
1 2 3 4
// Copyright 2015 The Chromium Authors. All rights reserved.
// 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 129
    double highlightElevation,
    double disabledElevation,
    EdgeInsetsGeometry padding,
    ShapeBorder shape,
130
    Clip clipBehavior = Clip.none,
131
    FocusNode focusNode,
132
    bool autofocus = false,
133 134 135
    MaterialTapTargetSize materialTapTargetSize,
    Duration animationDuration,
    Widget child,
136 137
  }) : assert(autofocus != null),
       assert(elevation == null || elevation >= 0.0),
138 139
       assert(focusElevation == null || focusElevation >= 0.0),
       assert(hoverElevation == null || hoverElevation >= 0.0),
140 141
       assert(highlightElevation == null || highlightElevation >= 0.0),
       assert(disabledElevation == null || disabledElevation >= 0.0),
142
       assert(clipBehavior != null),
143 144 145
       super(
         key: key,
         onPressed: onPressed,
146
         onLongPress: onLongPress,
147 148 149 150 151 152
         onHighlightChanged: onHighlightChanged,
         textTheme: textTheme,
         textColor: textColor,
         disabledTextColor: disabledTextColor,
         color: color,
         disabledColor: disabledColor,
153 154
         focusColor: focusColor,
         hoverColor: hoverColor,
155 156 157 158
         highlightColor: highlightColor,
         splashColor: splashColor,
         colorBrightness: colorBrightness,
         elevation: elevation,
159 160
         focusElevation: focusElevation,
         hoverElevation: hoverElevation,
161 162 163 164 165
         highlightElevation: highlightElevation,
         disabledElevation: disabledElevation,
         padding: padding,
         shape: shape,
         clipBehavior: clipBehavior,
166
         focusNode: focusNode,
167
         autofocus: autofocus,
168 169 170 171
         materialTapTargetSize: materialTapTargetSize,
         animationDuration: animationDuration,
         child: child,
       );
172 173 174 175 176 177 178

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

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

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

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