| // Copyright 2014 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'package:flutter/foundation.dart'; |
| import 'package:flutter/widgets.dart'; |
| |
| import 'color_scheme.dart'; |
| import 'colors.dart'; |
| import 'constants.dart'; |
| import 'material_button.dart'; |
| import 'material_state.dart'; |
| import 'theme.dart'; |
| import 'theme_data.dart' show MaterialTapTargetSize; |
| |
| // Examples can assume: |
| // late BuildContext context; |
| |
| /// Used with [ButtonTheme] and [ButtonThemeData] to define a button's base |
| /// colors, and the defaults for the button's minimum size, internal padding, |
| /// and shape. |
| enum ButtonTextTheme { |
| /// Button text is black or white depending on [ThemeData.brightness]. |
| normal, |
| |
| /// Button text is [ThemeData.accentColor]. |
| accent, |
| |
| /// Button text is based on [ThemeData.primaryColor]. |
| primary, |
| } |
| |
| /// Used with [ButtonTheme] and [ButtonThemeData] to define how the button bar |
| /// should size itself with either constraints or internal padding. |
| enum ButtonBarLayoutBehavior { |
| /// Button bars will be constrained to a minimum height of 52. |
| /// |
| /// This setting is require to create button bars which conform to the |
| /// Material Design specification. |
| constrained, |
| |
| /// Button bars will calculate their padding from the button theme padding. |
| padded, |
| } |
| |
| /// Used with [ButtonThemeData] to configure the color and geometry of buttons. |
| /// |
| /// This class is planned to be deprecated in a future release. |
| /// Please use one or more of these buttons and associated themes instead: |
| /// |
| /// * [ElevatedButton], [ElevatedButtonTheme], [ElevatedButtonThemeData], |
| /// * [FilledButton], [FilledButtonTheme], [FilledButtonThemeData], |
| /// * [OutlinedButton], [OutlinedButtonTheme], [OutlinedButtonThemeData] |
| /// * [TextButton], [TextButtonTheme], [TextButtonThemeData], |
| /// |
| /// A button theme can be specified as part of the overall Material theme |
| /// using [ThemeData.buttonTheme]. The Material theme's button theme data |
| /// can be overridden with [ButtonTheme]. |
| /// |
| /// The actual appearance of buttons depends on the button theme, the |
| /// button's enabled state, its elevation (if any), and the overall [Theme]. |
| /// |
| /// See also: |
| /// |
| /// * [RawMaterialButton], which can be used to configure a button that doesn't |
| /// depend on any inherited themes. |
| class ButtonTheme extends InheritedTheme { |
| /// Creates a button theme. |
| /// |
| /// The [textTheme], [minWidth], [height], and [colorScheme] arguments |
| /// must not be null. |
| ButtonTheme({ |
| super.key, |
| ButtonTextTheme textTheme = ButtonTextTheme.normal, |
| ButtonBarLayoutBehavior layoutBehavior = ButtonBarLayoutBehavior.padded, |
| double minWidth = 88.0, |
| double height = 36.0, |
| EdgeInsetsGeometry? padding, |
| ShapeBorder? shape, |
| bool alignedDropdown = false, |
| Color? buttonColor, |
| Color? disabledColor, |
| Color? focusColor, |
| Color? hoverColor, |
| Color? highlightColor, |
| Color? splashColor, |
| ColorScheme? colorScheme, |
| MaterialTapTargetSize? materialTapTargetSize, |
| required super.child, |
| }) : assert(minWidth >= 0.0), |
| assert(height >= 0.0), |
| data = ButtonThemeData( |
| textTheme: textTheme, |
| minWidth: minWidth, |
| height: height, |
| padding: padding, |
| shape: shape, |
| alignedDropdown: alignedDropdown, |
| layoutBehavior: layoutBehavior, |
| buttonColor: buttonColor, |
| disabledColor: disabledColor, |
| focusColor: focusColor, |
| hoverColor: hoverColor, |
| highlightColor: highlightColor, |
| splashColor: splashColor, |
| colorScheme: colorScheme, |
| materialTapTargetSize: materialTapTargetSize, |
| ); |
| |
| /// Creates a button theme from [data]. |
| /// |
| /// The [data] argument must not be null. |
| const ButtonTheme.fromButtonThemeData({ |
| super.key, |
| required this.data, |
| required super.child, |
| }); |
| |
| /// Specifies the color and geometry of buttons. |
| final ButtonThemeData data; |
| |
| /// The closest instance of this class that encloses the given context. |
| /// |
| /// Typical usage is as follows: |
| /// |
| /// ```dart |
| /// ButtonThemeData theme = ButtonTheme.of(context); |
| /// ``` |
| static ButtonThemeData of(BuildContext context) { |
| final ButtonTheme? inheritedButtonTheme = context.dependOnInheritedWidgetOfExactType<ButtonTheme>(); |
| ButtonThemeData? buttonTheme = inheritedButtonTheme?.data; |
| if (buttonTheme?.colorScheme == null) { // if buttonTheme or buttonTheme.colorScheme is null |
| final ThemeData theme = Theme.of(context); |
| buttonTheme ??= theme.buttonTheme; |
| if (buttonTheme.colorScheme == null) { |
| buttonTheme = buttonTheme.copyWith( |
| colorScheme: theme.buttonTheme.colorScheme ?? theme.colorScheme, |
| ); |
| assert(buttonTheme.colorScheme != null); |
| } |
| } |
| return buttonTheme!; |
| } |
| |
| @override |
| Widget wrap(BuildContext context, Widget child) { |
| return ButtonTheme.fromButtonThemeData(data: data, child: child); |
| } |
| |
| @override |
| bool updateShouldNotify(ButtonTheme oldWidget) => data != oldWidget.data; |
| } |
| |
| /// Used with [ButtonTheme] to configure the color and geometry of buttons. |
| /// |
| /// This class is planned to be deprecated in a future release. |
| /// Please use one or more of these buttons and associated themes instead: |
| /// |
| /// * [TextButton], [TextButtonTheme], [TextButtonThemeData], |
| /// * [ElevatedButton], [ElevatedButtonTheme], [ElevatedButtonThemeData], |
| /// * [OutlinedButton], [OutlinedButtonTheme], [OutlinedButtonThemeData] |
| /// |
| /// A button theme can be specified as part of the overall Material theme |
| /// using [ThemeData.buttonTheme]. The Material theme's button theme data |
| /// can be overridden with [ButtonTheme]. |
| @immutable |
| class ButtonThemeData with Diagnosticable { |
| /// Create a button theme object that can be used with [ButtonTheme] |
| /// or [ThemeData]. |
| /// |
| /// The [textTheme], [minWidth], [height], [alignedDropdown], and |
| /// [layoutBehavior] parameters must not be null. The [minWidth] and |
| /// [height] parameters must greater than or equal to zero. |
| /// |
| /// The ButtonTheme's methods that have a [MaterialButton] parameter and |
| /// have a name with a `get` prefix are used to configure a |
| /// [RawMaterialButton]. |
| const ButtonThemeData({ |
| this.textTheme = ButtonTextTheme.normal, |
| this.minWidth = 88.0, |
| this.height = 36.0, |
| EdgeInsetsGeometry? padding, |
| ShapeBorder? shape, |
| this.layoutBehavior = ButtonBarLayoutBehavior.padded, |
| this.alignedDropdown = false, |
| Color? buttonColor, |
| Color? disabledColor, |
| Color? focusColor, |
| Color? hoverColor, |
| Color? highlightColor, |
| Color? splashColor, |
| this.colorScheme, |
| MaterialTapTargetSize? materialTapTargetSize, |
| }) : assert(minWidth >= 0.0), |
| assert(height >= 0.0), |
| _buttonColor = buttonColor, |
| _disabledColor = disabledColor, |
| _focusColor = focusColor, |
| _hoverColor = hoverColor, |
| _highlightColor = highlightColor, |
| _splashColor = splashColor, |
| _padding = padding, |
| _shape = shape, |
| _materialTapTargetSize = materialTapTargetSize; |
| |
| /// The minimum width for buttons. |
| /// |
| /// The actual horizontal space allocated for a button's child is |
| /// at least this value less the theme's horizontal [padding]. |
| /// |
| /// Defaults to 88.0 logical pixels. |
| final double minWidth; |
| |
| /// The minimum height for buttons. |
| /// |
| /// Defaults to 36.0 logical pixels. |
| final double height; |
| |
| /// Defines a button's base colors, and the defaults for the button's minimum |
| /// size, internal padding, and shape. |
| /// |
| /// Despite the name, this property is not a [TextTheme], its value is not a |
| /// collection of [TextStyle]s. |
| final ButtonTextTheme textTheme; |
| |
| /// Defines whether a [ButtonBar] should size itself with a minimum size |
| /// constraint or with padding. |
| /// |
| /// Defaults to [ButtonBarLayoutBehavior.padded]. |
| final ButtonBarLayoutBehavior layoutBehavior; |
| |
| /// Convenience that returns [minWidth] and [height] as a |
| /// [BoxConstraints] object. |
| BoxConstraints get constraints { |
| return BoxConstraints( |
| minWidth: minWidth, |
| minHeight: height, |
| ); |
| } |
| |
| /// Padding for a button's child (typically the button's label). |
| /// |
| /// Defaults to 24.0 on the left and right if [textTheme] is |
| /// [ButtonTextTheme.primary], 16.0 on the left and right otherwise. |
| /// |
| /// See also: |
| /// |
| /// * [getPadding], which is used to calculate padding for the [button]'s |
| /// child (typically the button's label). |
| EdgeInsetsGeometry get padding { |
| if (_padding != null) { |
| return _padding!; |
| } |
| switch (textTheme) { |
| case ButtonTextTheme.normal: |
| case ButtonTextTheme.accent: |
| return const EdgeInsets.symmetric(horizontal: 16.0); |
| case ButtonTextTheme.primary: |
| return const EdgeInsets.symmetric(horizontal: 24.0); |
| } |
| } |
| final EdgeInsetsGeometry? _padding; |
| |
| /// The shape of a button's material. |
| /// |
| /// The button's highlight and splash are clipped to this shape. If the |
| /// button has an elevation, then its drop shadow is defined by this |
| /// shape as well. |
| /// |
| /// Defaults to a rounded rectangle with circular corner radii of 4.0 if |
| /// [textTheme] is [ButtonTextTheme.primary], a rounded rectangle with |
| /// circular corner radii of 2.0 otherwise. |
| /// |
| /// See also: |
| /// |
| /// * [getShape], which is used to calculate the shape of the [button]'s |
| /// [Material]. |
| ShapeBorder get shape { |
| if (_shape != null) { |
| return _shape!; |
| } |
| switch (textTheme) { |
| case ButtonTextTheme.normal: |
| case ButtonTextTheme.accent: |
| return const RoundedRectangleBorder( |
| borderRadius: BorderRadius.all(Radius.circular(2.0)), |
| ); |
| case ButtonTextTheme.primary: |
| return const RoundedRectangleBorder( |
| borderRadius: BorderRadius.all(Radius.circular(4.0)), |
| ); |
| } |
| } |
| final ShapeBorder? _shape; |
| |
| /// If true, then a [DropdownButton] menu's width will match the button's |
| /// width. |
| /// |
| /// If false (the default), then the dropdown's menu will be wider than |
| /// its button. In either case the dropdown button will line up the leading |
| /// edge of the menu's value with the leading edge of the values |
| /// displayed by the menu items. |
| /// |
| /// This property only affects [DropdownButton] and its menu. |
| final bool alignedDropdown; |
| |
| /// The background fill color. |
| /// |
| /// This property is null by default. |
| /// |
| /// If the button is in the focused, hovering, or highlighted state, then the |
| /// [focusColor], [hoverColor], or [highlightColor] will take precedence over |
| /// the [buttonColor]. |
| /// |
| /// See also: |
| /// |
| /// * [getFillColor], which is used to compute the background fill color. |
| final Color? _buttonColor; |
| |
| /// The background fill color when disabled. |
| /// |
| /// This property is null by default. |
| /// |
| /// See also: |
| /// |
| /// * [getDisabledFillColor], which is to compute background fill color for |
| /// disabled state. |
| final Color? _disabledColor; |
| |
| /// The fill color of the button when it has the input focus. |
| /// |
| /// This property is null by default. |
| /// |
| /// If the button is in the hovering or highlighted state, then the [hoverColor] |
| /// or [highlightColor] will take precedence over the [focusColor]. |
| /// |
| /// See also: |
| /// |
| /// * [getFocusColor], which is used to compute the fill color of the button |
| /// when it has input focus. |
| final Color? _focusColor; |
| |
| /// The fill color of the button when a pointer is hovering over it. |
| /// |
| /// This property is null by default. |
| /// |
| /// If the button is in the highlighted state, then the [highlightColor] will |
| /// take precedence over the [hoverColor]. |
| /// |
| /// See also: |
| /// |
| /// * [getHoverColor], which is used to compute the fill color of the button |
| /// when it has input focus. |
| final Color? _hoverColor; |
| |
| /// The color of the overlay that appears when a button is pressed. |
| /// |
| /// This property is null by default. |
| /// |
| /// See also: |
| /// |
| /// * [getHighlightColor], which is used to compute the color of the overlay |
| /// that appears when the [button] is pressed. |
| final Color? _highlightColor; |
| |
| /// The color of the ink "splash" overlay that appears when a button is tapped. |
| /// |
| /// This property is null by default. |
| /// |
| /// See also: |
| /// |
| /// * [getSplashColor], which is used to compute the color of the ink |
| /// "splash" overlay that appears when the (enabled) [button] is tapped. |
| final Color? _splashColor; |
| |
| /// A set of thirteen colors that can be used to derive the button theme's |
| /// colors. |
| /// |
| /// This property was added much later than the theme's set of highly specific |
| /// colors, like [ThemeData.highlightColor] and [ThemeData.splashColor] etc. |
| /// |
| /// The colors for new button classes can be defined exclusively in terms of |
| /// [colorScheme]. When it's possible, the existing buttons will (continue to) |
| /// gradually migrate to it. |
| final ColorScheme? colorScheme; |
| |
| // The minimum size of a button's tap target. |
| // |
| // This property is null by default. |
| final MaterialTapTargetSize? _materialTapTargetSize; |
| |
| /// The [button]'s overall brightness. |
| /// |
| /// Returns the button's [MaterialButton.colorBrightness] if it is non-null, |
| /// otherwise the color scheme's [ColorScheme.brightness] is returned. |
| Brightness getBrightness(MaterialButton button) { |
| return button.colorBrightness ?? colorScheme!.brightness; |
| } |
| |
| /// Defines the [button]'s base colors, and the defaults for the button's |
| /// minimum size, internal padding, and shape. |
| /// |
| /// Despite the name, this property is not the [TextTheme] whose |
| /// [TextTheme.button] is used as the button text's [TextStyle]. |
| ButtonTextTheme getTextTheme(MaterialButton button) => button.textTheme ?? textTheme; |
| |
| /// The foreground color of the [button]'s text and icon when |
| /// [MaterialButton.onPressed] is null (when MaterialButton.enabled is false). |
| /// |
| /// Returns the button's [MaterialButton.disabledColor] if it is non-null. |
| /// Otherwise the color scheme's [ColorScheme.onSurface] color is returned |
| /// with its opacity set to 0.38. |
| /// |
| /// If [MaterialButton.textColor] is a [MaterialStateProperty<Color>], it will be |
| /// used as the `disabledTextColor`. It will be resolved in the [MaterialState.disabled] state. |
| Color getDisabledTextColor(MaterialButton button) { |
| return button.textColor ?? button.disabledTextColor ?? colorScheme!.onSurface.withOpacity(0.38); |
| } |
| |
| /// The [button]'s background color when [MaterialButton.onPressed] is null |
| /// (when [MaterialButton.enabled] is false). |
| /// |
| /// Returns the button's [MaterialButton.disabledColor] if it is non-null. |
| /// |
| /// Otherwise the value of the `disabledColor` constructor parameter |
| /// is returned, if it is non-null. |
| /// |
| /// Otherwise the color scheme's [ColorScheme.onSurface] color is returned |
| /// with its opacity set to 0.38. |
| Color getDisabledFillColor(MaterialButton button) { |
| return button.disabledColor ?? _disabledColor ?? colorScheme!.onSurface.withOpacity(0.38); |
| } |
| |
| /// The button's background fill color or null for buttons that don't have |
| /// a background color. |
| /// |
| /// Returns [MaterialButton.color] if it is non-null and the button |
| /// is enabled. |
| /// |
| /// Otherwise, returns [MaterialButton.disabledColor] if it is non-null and |
| /// the button is disabled. |
| /// |
| /// Otherwise the fill color depends on the value of [getTextTheme]. |
| /// |
| /// * [ButtonTextTheme.normal] or [ButtonTextTheme.accent], the |
| /// color scheme's [ColorScheme.primary] color if the [button] is enabled |
| /// the value of [getDisabledFillColor] otherwise. |
| /// * [ButtonTextTheme.primary], if the [button] is enabled then the value |
| /// of the `buttonColor` constructor parameter if it is non-null, |
| /// otherwise the color scheme's ColorScheme.primary color. If the button |
| /// is not enabled then the colorScheme's [ColorScheme.onSurface] color |
| /// with opacity 0.12. |
| Color? getFillColor(MaterialButton button) { |
| final Color? fillColor = button.enabled ? button.color : button.disabledColor; |
| if (fillColor != null) { |
| return fillColor; |
| } |
| |
| if (button.runtimeType == MaterialButton) { |
| return null; |
| } |
| |
| if (button.enabled && _buttonColor != null) { |
| return _buttonColor; |
| } |
| |
| switch (getTextTheme(button)) { |
| case ButtonTextTheme.normal: |
| case ButtonTextTheme.accent: |
| return button.enabled ? colorScheme!.primary : getDisabledFillColor(button); |
| case ButtonTextTheme.primary: |
| return button.enabled |
| ? _buttonColor ?? colorScheme!.primary |
| : colorScheme!.onSurface.withOpacity(0.12); |
| } |
| } |
| |
| /// The foreground color of the [button]'s text and icon. |
| /// |
| /// If [button] is not [MaterialButton.enabled], the value of |
| /// [getDisabledTextColor] is returned. If the button is enabled and |
| /// [MaterialButton.textColor] is non-null, then [MaterialButton.textColor] |
| /// is returned. |
| /// |
| /// Otherwise the text color depends on the value of [getTextTheme] |
| /// and [getBrightness]. |
| /// |
| /// * [ButtonTextTheme.normal]: [Colors.white] is used if [getBrightness] |
| /// resolves to [Brightness.dark]. [Colors.black87] is used if |
| /// [getBrightness] resolves to [Brightness.light]. |
| /// * [ButtonTextTheme.accent]: [ColorScheme.secondary] of [colorScheme]. |
| /// * [ButtonTextTheme.primary]: If [getFillColor] is dark then [Colors.white], |
| /// otherwise [Colors.black]. |
| Color getTextColor(MaterialButton button) { |
| if (!button.enabled) { |
| return getDisabledTextColor(button); |
| } |
| |
| if (button.textColor != null) { |
| return button.textColor!; |
| } |
| |
| switch (getTextTheme(button)) { |
| case ButtonTextTheme.normal: |
| return getBrightness(button) == Brightness.dark ? Colors.white : Colors.black87; |
| |
| case ButtonTextTheme.accent: |
| return colorScheme!.secondary; |
| |
| case ButtonTextTheme.primary: |
| final Color? fillColor = getFillColor(button); |
| final bool fillIsDark = fillColor != null |
| ? ThemeData.estimateBrightnessForColor(fillColor) == Brightness.dark |
| : getBrightness(button) == Brightness.dark; |
| return fillIsDark ? Colors.white : Colors.black; |
| } |
| } |
| |
| /// The color of the ink "splash" overlay that appears when the (enabled) |
| /// [button] is tapped. |
| /// |
| /// Returns the button's [MaterialButton.splashColor] if it is non-null. |
| /// |
| /// Otherwise, returns the value of the `splashColor` constructor parameter |
| /// it is non-null. |
| /// |
| /// Otherwise, returns the value of the `splashColor` constructor parameter |
| /// if it is non-null and [getTextTheme] is not [ButtonTextTheme.primary]. |
| /// |
| /// Otherwise, returns [getTextColor] with an opacity of 0.12. |
| Color getSplashColor(MaterialButton button) { |
| if (button.splashColor != null) { |
| return button.splashColor!; |
| } |
| |
| if (_splashColor != null) { |
| switch (getTextTheme(button)) { |
| case ButtonTextTheme.normal: |
| case ButtonTextTheme.accent: |
| return _splashColor!; |
| case ButtonTextTheme.primary: |
| break; |
| } |
| } |
| |
| return getTextColor(button).withOpacity(0.12); |
| } |
| |
| /// The fill color of the button when it has input focus. |
| /// |
| /// Returns the button's [MaterialButton.focusColor] if it is non-null. |
| /// Otherwise the focus color depends on [getTextTheme]: |
| /// |
| /// * [ButtonTextTheme.normal], [ButtonTextTheme.accent]: returns the |
| /// value of the `focusColor` constructor parameter if it is non-null, |
| /// otherwise the value of [getTextColor] with opacity 0.12. |
| /// * [ButtonTextTheme.primary], returns [Colors.transparent]. |
| Color getFocusColor(MaterialButton button) { |
| return button.focusColor ?? _focusColor ?? getTextColor(button).withOpacity(0.12); |
| } |
| |
| /// The fill color of the button when it has input focus. |
| /// |
| /// Returns the button's [MaterialButton.focusColor] if it is non-null. |
| /// Otherwise the focus color depends on [getTextTheme]: |
| /// |
| /// * [ButtonTextTheme.normal], [ButtonTextTheme.accent], |
| /// [ButtonTextTheme.primary]: returns the value of the `focusColor` |
| /// constructor parameter if it is non-null, otherwise the value of |
| /// [getTextColor] with opacity 0.04. |
| Color getHoverColor(MaterialButton button) { |
| return button.hoverColor ?? _hoverColor ?? getTextColor(button).withOpacity(0.04); |
| } |
| |
| /// The color of the overlay that appears when the [button] is pressed. |
| /// |
| /// Returns the button's [MaterialButton.highlightColor] if it is non-null. |
| /// Otherwise the highlight color depends on [getTextTheme]: |
| /// |
| /// * [ButtonTextTheme.normal], [ButtonTextTheme.accent]: returns the |
| /// value of the `highlightColor` constructor parameter if it is non-null, |
| /// otherwise the value of [getTextColor] with opacity 0.16. |
| /// * [ButtonTextTheme.primary], returns [Colors.transparent]. |
| Color getHighlightColor(MaterialButton button) { |
| if (button.highlightColor != null) { |
| return button.highlightColor!; |
| } |
| |
| switch (getTextTheme(button)) { |
| case ButtonTextTheme.normal: |
| case ButtonTextTheme.accent: |
| return _highlightColor ?? getTextColor(button).withOpacity(0.16); |
| case ButtonTextTheme.primary: |
| return Colors.transparent; |
| } |
| } |
| |
| /// The [button]'s elevation when it is enabled and has not been pressed. |
| /// |
| /// Returns the button's [MaterialButton.elevation] if it is non-null, |
| /// otherwise it is 2.0. |
| double getElevation(MaterialButton button) => button.elevation ?? 2.0; |
| |
| /// The [button]'s elevation when it is enabled and has focus. |
| /// |
| /// Returns the button's [MaterialButton.focusElevation] if it is non-null, |
| /// otherwise the highlight elevation is 4.0. |
| double getFocusElevation(MaterialButton button) => button.focusElevation ?? 4.0; |
| |
| /// The [button]'s elevation when it is enabled and has focus. |
| /// |
| /// Returns the button's [MaterialButton.hoverElevation] if it is non-null, |
| /// otherwise the highlight elevation is 4.0. |
| double getHoverElevation(MaterialButton button) => button.hoverElevation ?? 4.0; |
| |
| /// The [button]'s elevation when it is enabled and has been pressed. |
| /// |
| /// Returns the button's [MaterialButton.highlightElevation] if it is non-null, |
| /// otherwise the highlight elevation is 8.0. |
| double getHighlightElevation(MaterialButton button) => button.highlightElevation ?? 8.0; |
| |
| /// The [button]'s elevation when [MaterialButton.onPressed] is null (when |
| /// MaterialButton.enabled is false). |
| /// |
| /// Returns the button's [MaterialButton.elevation] if it is non-null. |
| /// |
| /// Otherwise the disabled elevation is 0.0. |
| double getDisabledElevation(MaterialButton button) => button.disabledElevation ?? 0.0; |
| |
| /// Padding for the [button]'s child (typically the button's label). |
| /// |
| /// Returns the button's [MaterialButton.padding] if it is non-null, |
| /// otherwise, returns the `padding` of the constructor parameter if it is |
| /// non-null. |
| /// |
| /// Otherwise, returns horizontal padding of 24.0 on the left and right if |
| /// [getTextTheme] is [ButtonTextTheme.primary], 16.0 on the left and right |
| /// otherwise. |
| EdgeInsetsGeometry getPadding(MaterialButton button) { |
| if (button.padding != null) { |
| return button.padding!; |
| } |
| |
| if (button is MaterialButtonWithIconMixin) { |
| return const EdgeInsetsDirectional.only(start: 12.0, end: 16.0); |
| } |
| |
| if (_padding != null) { |
| return _padding!; |
| } |
| |
| switch (getTextTheme(button)) { |
| case ButtonTextTheme.normal: |
| case ButtonTextTheme.accent: |
| return const EdgeInsets.symmetric(horizontal: 16.0); |
| case ButtonTextTheme.primary: |
| return const EdgeInsets.symmetric(horizontal: 24.0); |
| } |
| } |
| |
| /// The shape of the [button]'s [Material]. |
| /// |
| /// Returns the button's [MaterialButton.shape] if it is non-null, otherwise |
| /// [shape] is returned. |
| ShapeBorder getShape(MaterialButton button) => button.shape ?? shape; |
| |
| /// The duration of the [button]'s highlight animation. |
| /// |
| /// Returns the button's [MaterialButton.animationDuration] it if is non-null, |
| /// otherwise 200ms. |
| Duration getAnimationDuration(MaterialButton button) { |
| return button.animationDuration ?? kThemeChangeDuration; |
| } |
| |
| /// The [BoxConstraints] that the define the [button]'s size. |
| /// |
| /// By default this method just returns [constraints]. Subclasses |
| /// could override this method to return a value that was, |
| /// for example, based on the button's type. |
| BoxConstraints getConstraints(MaterialButton button) => constraints; |
| |
| /// The minimum size of the [button]'s tap target. |
| /// |
| /// Returns the button's [MaterialButton.materialTapTargetSize] if it is non-null. |
| /// |
| /// Otherwise the value of the `materialTapTargetSize` constructor |
| /// parameter is returned if that's non-null. |
| /// |
| /// Otherwise [MaterialTapTargetSize.padded] is returned. |
| MaterialTapTargetSize getMaterialTapTargetSize(MaterialButton button) { |
| return button.materialTapTargetSize ?? _materialTapTargetSize ?? MaterialTapTargetSize.padded; |
| } |
| |
| /// Creates a copy of this button theme data object with the matching fields |
| /// replaced with the non-null parameter values. |
| ButtonThemeData copyWith({ |
| ButtonTextTheme? textTheme, |
| ButtonBarLayoutBehavior? layoutBehavior, |
| double? minWidth, |
| double? height, |
| EdgeInsetsGeometry? padding, |
| ShapeBorder? shape, |
| bool? alignedDropdown, |
| Color? buttonColor, |
| Color? disabledColor, |
| Color? focusColor, |
| Color? hoverColor, |
| Color? highlightColor, |
| Color? splashColor, |
| ColorScheme? colorScheme, |
| MaterialTapTargetSize? materialTapTargetSize, |
| }) { |
| return ButtonThemeData( |
| textTheme: textTheme ?? this.textTheme, |
| layoutBehavior: layoutBehavior ?? this.layoutBehavior, |
| minWidth: minWidth ?? this.minWidth, |
| height: height ?? this.height, |
| padding: padding ?? this.padding, |
| shape: shape ?? this.shape, |
| alignedDropdown: alignedDropdown ?? this.alignedDropdown, |
| buttonColor: buttonColor ?? _buttonColor, |
| disabledColor: disabledColor ?? _disabledColor, |
| focusColor: focusColor ?? _focusColor, |
| hoverColor: hoverColor ?? _hoverColor, |
| highlightColor: highlightColor ?? _highlightColor, |
| splashColor: splashColor ?? _splashColor, |
| colorScheme: colorScheme ?? this.colorScheme, |
| materialTapTargetSize: materialTapTargetSize ?? _materialTapTargetSize, |
| ); |
| } |
| |
| @override |
| bool operator ==(Object other) { |
| if (other.runtimeType != runtimeType) { |
| return false; |
| } |
| return other is ButtonThemeData |
| && other.textTheme == textTheme |
| && other.minWidth == minWidth |
| && other.height == height |
| && other.padding == padding |
| && other.shape == shape |
| && other.alignedDropdown == alignedDropdown |
| && other._buttonColor == _buttonColor |
| && other._disabledColor == _disabledColor |
| && other._focusColor == _focusColor |
| && other._hoverColor == _hoverColor |
| && other._highlightColor == _highlightColor |
| && other._splashColor == _splashColor |
| && other.colorScheme == colorScheme |
| && other._materialTapTargetSize == _materialTapTargetSize; |
| } |
| |
| @override |
| int get hashCode => Object.hash( |
| textTheme, |
| minWidth, |
| height, |
| padding, |
| shape, |
| alignedDropdown, |
| _buttonColor, |
| _disabledColor, |
| _focusColor, |
| _hoverColor, |
| _highlightColor, |
| _splashColor, |
| colorScheme, |
| _materialTapTargetSize, |
| ); |
| |
| @override |
| void debugFillProperties(DiagnosticPropertiesBuilder properties) { |
| super.debugFillProperties(properties); |
| const ButtonThemeData defaultTheme = ButtonThemeData(); |
| properties.add(EnumProperty<ButtonTextTheme>('textTheme', textTheme, defaultValue: defaultTheme.textTheme)); |
| properties.add(DoubleProperty('minWidth', minWidth, defaultValue: defaultTheme.minWidth)); |
| properties.add(DoubleProperty('height', height, defaultValue: defaultTheme.height)); |
| properties.add(DiagnosticsProperty<EdgeInsetsGeometry>('padding', padding, defaultValue: defaultTheme.padding)); |
| properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: defaultTheme.shape)); |
| properties.add(FlagProperty('alignedDropdown', |
| value: alignedDropdown, |
| defaultValue: defaultTheme.alignedDropdown, |
| ifTrue: 'dropdown width matches button', |
| )); |
| properties.add(ColorProperty('buttonColor', _buttonColor, defaultValue: null)); |
| properties.add(ColorProperty('disabledColor', _disabledColor, defaultValue: null)); |
| properties.add(ColorProperty('focusColor', _focusColor, defaultValue: null)); |
| properties.add(ColorProperty('hoverColor', _hoverColor, defaultValue: null)); |
| properties.add(ColorProperty('highlightColor', _highlightColor, defaultValue: null)); |
| properties.add(ColorProperty('splashColor', _splashColor, defaultValue: null)); |
| properties.add(DiagnosticsProperty<ColorScheme>('colorScheme', colorScheme, defaultValue: defaultTheme.colorScheme)); |
| properties.add(DiagnosticsProperty<MaterialTapTargetSize>('materialTapTargetSize', _materialTapTargetSize, defaultValue: null)); |
| } |
| } |