mirror of
https://github.com/flutter/flutter
synced 2024-08-27 03:50:33 +00:00
Migrate IconButton
to Material 3 - Part 1 (#105176)
* Added standard IconButton for M3 with new ButtonStyle field * Added IconButton examples for standard, filled, filled_tonal, and outlined types Co-authored-by: Qun Cheng <quncheng@google.com>
This commit is contained in:
parent
1718519188
commit
66a84d1fed
|
@ -22,6 +22,7 @@ import 'package:gen_defaults/button_template.dart';
|
|||
import 'package:gen_defaults/card_template.dart';
|
||||
import 'package:gen_defaults/dialog_template.dart';
|
||||
import 'package:gen_defaults/fab_template.dart';
|
||||
import 'package:gen_defaults/icon_button_template.dart';
|
||||
import 'package:gen_defaults/navigation_bar_template.dart';
|
||||
import 'package:gen_defaults/navigation_rail_template.dart';
|
||||
import 'package:gen_defaults/surface_tint.dart';
|
||||
|
@ -55,6 +56,9 @@ Future<void> main(List<String> args) async {
|
|||
'fab_large_primary.json',
|
||||
'fab_primary.json',
|
||||
'fab_small_primary.json',
|
||||
'icon_button.json',
|
||||
'icon_button_filled.json',
|
||||
'icon_button_filled_tonal.json',
|
||||
'motion.json',
|
||||
'navigation_bar.json',
|
||||
'navigation_rail.json',
|
||||
|
@ -86,6 +90,7 @@ Future<void> main(List<String> args) async {
|
|||
CardTemplate('$materialLib/card.dart', tokens).updateFile();
|
||||
DialogTemplate('$materialLib/dialog.dart', tokens).updateFile();
|
||||
FABTemplate('$materialLib/floating_action_button.dart', tokens).updateFile();
|
||||
IconButtonTemplate('$materialLib/icon_button.dart', tokens).updateFile();
|
||||
NavigationBarTemplate('$materialLib/navigation_bar.dart', tokens).updateFile();
|
||||
NavigationRailTemplate('$materialLib/navigation_rail.dart', tokens).updateFile();
|
||||
SurfaceTintTemplate('$materialLib/elevation_overlay.dart', tokens).updateFile();
|
||||
|
|
99
dev/tools/gen_defaults/lib/icon_button_template.dart
Normal file
99
dev/tools/gen_defaults/lib/icon_button_template.dart
Normal file
|
@ -0,0 +1,99 @@
|
|||
// 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 'template.dart';
|
||||
|
||||
class IconButtonTemplate extends TokenTemplate {
|
||||
const IconButtonTemplate(super.fileName, super.tokens)
|
||||
: super(colorSchemePrefix: '_colors.',
|
||||
);
|
||||
|
||||
@override
|
||||
String generate() => '''
|
||||
// Generated version ${tokens["version"]}
|
||||
class _TokenDefaultsM3 extends ButtonStyle {
|
||||
_TokenDefaultsM3(this.context)
|
||||
: super(
|
||||
animationDuration: kThemeChangeDuration,
|
||||
enableFeedback: true,
|
||||
alignment: Alignment.center,
|
||||
);
|
||||
|
||||
final BuildContext context;
|
||||
late final ColorScheme _colors = Theme.of(context).colorScheme;
|
||||
|
||||
// No default text style
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?>? get backgroundColor =>
|
||||
ButtonStyleButton.allOrNull<Color>(Colors.transparent);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?>? get foregroundColor =>
|
||||
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.disabled))
|
||||
return ${componentColor('md.comp.icon-button.disabled.icon')};
|
||||
return ${componentColor('md.comp.icon-button.unselected.icon')};
|
||||
});
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?>? get overlayColor =>
|
||||
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.hovered))
|
||||
return ${componentColor('md.comp.icon-button.unselected.hover.state-layer')};
|
||||
if (states.contains(MaterialState.focused))
|
||||
return ${componentColor('md.comp.icon-button.unselected.focus.state-layer')};
|
||||
if (states.contains(MaterialState.pressed))
|
||||
return ${componentColor('md.comp.icon-button.unselected.pressed.state-layer')};
|
||||
return null;
|
||||
});
|
||||
|
||||
// No default shadow color
|
||||
|
||||
// No default surface tint color
|
||||
|
||||
@override
|
||||
MaterialStateProperty<double>? get elevation =>
|
||||
ButtonStyleButton.allOrNull<double>(0.0);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
|
||||
ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(const EdgeInsets.all(8.0));
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get minimumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(const Size(${tokens["md.comp.icon-button.state-layer.size"]}, ${tokens["md.comp.icon-button.state-layer.size"]}));
|
||||
|
||||
// No default fixedSize
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get maximumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(Size.infinite);
|
||||
|
||||
// No default side
|
||||
|
||||
@override
|
||||
MaterialStateProperty<OutlinedBorder>? get shape =>
|
||||
ButtonStyleButton.allOrNull<OutlinedBorder>(${shape("md.comp.icon-button.state-layer")});
|
||||
|
||||
@override
|
||||
MaterialStateProperty<MouseCursor?>? get mouseCursor =>
|
||||
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.disabled))
|
||||
return SystemMouseCursors.basic;
|
||||
return SystemMouseCursors.click;
|
||||
});
|
||||
|
||||
@override
|
||||
VisualDensity? get visualDensity => Theme.of(context).visualDensity;
|
||||
|
||||
@override
|
||||
MaterialTapTargetSize? get tapTargetSize => Theme.of(context).materialTapTargetSize;
|
||||
|
||||
@override
|
||||
InteractiveInkFeatureFactory? get splashFactory => Theme.of(context).splashFactory;
|
||||
}
|
||||
''';
|
||||
|
||||
}
|
118
examples/api/lib/material/icon_button/icon_button.2.dart
Normal file
118
examples/api/lib/material/icon_button/icon_button.2.dart
Normal file
|
@ -0,0 +1,118 @@
|
|||
// 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.
|
||||
|
||||
// Flutter code sample for IconButton
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const IconButtonApp());
|
||||
}
|
||||
|
||||
class IconButtonApp extends StatelessWidget {
|
||||
const IconButtonApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
theme: ThemeData(colorSchemeSeed: const Color(0xff6750a4), useMaterial3: true),
|
||||
title: 'Icon Button Types',
|
||||
home: const Scaffold(
|
||||
body: ButtonTypesExample(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ButtonTypesExample extends StatelessWidget {
|
||||
const ButtonTypesExample({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: Row(
|
||||
children: const <Widget>[
|
||||
Spacer(),
|
||||
ButtonTypesGroup(enabled: true),
|
||||
ButtonTypesGroup(enabled: false),
|
||||
Spacer(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ButtonTypesGroup extends StatelessWidget {
|
||||
const ButtonTypesGroup({ super.key, required this.enabled });
|
||||
|
||||
final bool enabled;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final VoidCallback? onPressed = enabled ? () {} : null;
|
||||
final ColorScheme colors = Theme.of(context).colorScheme;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: <Widget>[
|
||||
IconButton(icon: const Icon(Icons.filter_drama), onPressed: onPressed),
|
||||
|
||||
// Use a standard IconButton with specific style to implement the
|
||||
// 'Filled' type.
|
||||
IconButton(
|
||||
icon: const Icon(Icons.filter_drama),
|
||||
onPressed: onPressed,
|
||||
style: IconButton.styleFrom(
|
||||
foregroundColor: colors.onPrimary,
|
||||
backgroundColor: colors.primary,
|
||||
disabledBackgroundColor: colors.onSurface.withOpacity(0.12),
|
||||
hoverColor: colors.onPrimary.withOpacity(0.08),
|
||||
focusColor: colors.onPrimary.withOpacity(0.12),
|
||||
highlightColor: colors.onPrimary.withOpacity(0.12),
|
||||
)
|
||||
),
|
||||
|
||||
// Use a standard IconButton with specific style to implement the
|
||||
// 'Filled Tonal' type.
|
||||
IconButton(
|
||||
icon: const Icon(Icons.filter_drama),
|
||||
onPressed: onPressed,
|
||||
style: IconButton.styleFrom(
|
||||
foregroundColor: colors.onSecondaryContainer,
|
||||
backgroundColor: colors.secondaryContainer,
|
||||
disabledBackgroundColor: colors.onSurface.withOpacity(0.12),
|
||||
hoverColor: colors.onSecondaryContainer.withOpacity(0.08),
|
||||
focusColor: colors.onSecondaryContainer.withOpacity(0.12),
|
||||
highlightColor: colors.onSecondaryContainer.withOpacity(0.12),
|
||||
),
|
||||
),
|
||||
|
||||
// Use a standard IconButton with specific style to implement the
|
||||
// 'Outlined' type.
|
||||
IconButton(
|
||||
icon: const Icon(Icons.filter_drama),
|
||||
onPressed: onPressed,
|
||||
style: IconButton.styleFrom(
|
||||
focusColor: colors.onSurfaceVariant.withOpacity(0.12),
|
||||
highlightColor: colors.onSurface.withOpacity(0.12),
|
||||
side: onPressed == null
|
||||
? BorderSide(color: Theme.of(context).colorScheme.onSurface.withOpacity(0.12))
|
||||
: BorderSide(color: colors.outline),
|
||||
).copyWith(
|
||||
foregroundColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.pressed)) {
|
||||
return colors.onSurface;
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -8,11 +8,16 @@ import 'package:flutter/foundation.dart';
|
|||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'button_style.dart';
|
||||
import 'button_style_button.dart';
|
||||
import 'color_scheme.dart';
|
||||
import 'colors.dart';
|
||||
import 'constants.dart';
|
||||
import 'debug.dart';
|
||||
import 'icons.dart';
|
||||
import 'ink_well.dart';
|
||||
import 'material.dart';
|
||||
import 'material_state.dart';
|
||||
import 'theme.dart';
|
||||
import 'theme_data.dart';
|
||||
import 'tooltip.dart';
|
||||
|
@ -92,6 +97,17 @@ const double _kMinButtonSize = kMinInteractiveDimension;
|
|||
/// ** See code in examples/api/lib/material/icon_button/icon_button.1.dart **
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// Material Design 3 introduced new types (standard and contained) of [IconButton]s.
|
||||
/// The default [IconButton] is the standard type, and contained icon buttons can be produced
|
||||
/// by configuring the [IconButton] widget's properties.
|
||||
///
|
||||
/// {@tool dartpad}
|
||||
/// This sample shows creation of [IconButton] widgets for standard, filled,
|
||||
/// filled tonal and outlined types, as described in: https://m3.material.io/components/icon-buttons/overview
|
||||
///
|
||||
/// ** See code in examples/api/lib/material/icon_button/icon_button.2.dart **
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [Icons], the library of Material Icons.
|
||||
|
@ -134,6 +150,7 @@ class IconButton extends StatelessWidget {
|
|||
this.tooltip,
|
||||
this.enableFeedback = true,
|
||||
this.constraints,
|
||||
this.style,
|
||||
required this.icon,
|
||||
}) : assert(padding != null),
|
||||
assert(alignment != null),
|
||||
|
@ -184,6 +201,8 @@ class IconButton extends StatelessWidget {
|
|||
|
||||
/// The splash radius.
|
||||
///
|
||||
/// If [ThemeData.useMaterial3] is set to true, this will not be used.
|
||||
///
|
||||
/// If null, default splash radius of [Material.defaultSplashRadius] is used.
|
||||
final double? splashRadius;
|
||||
|
||||
|
@ -230,6 +249,8 @@ class IconButton extends StatelessWidget {
|
|||
/// fill the button area if the touch is held for long enough time. If the splash
|
||||
/// color has transparency then the highlight and button color will show through.
|
||||
///
|
||||
/// If [ThemeData.useMaterial3] is set to true, this will not be used.
|
||||
///
|
||||
/// Defaults to the Theme's splash color, [ThemeData.splashColor].
|
||||
final Color? splashColor;
|
||||
|
||||
|
@ -301,10 +322,125 @@ class IconButton extends StatelessWidget {
|
|||
/// and `Theme.of(context).visualDensity` otherwise.
|
||||
final BoxConstraints? constraints;
|
||||
|
||||
/// Customizes this button's appearance.
|
||||
///
|
||||
/// Non-null properties of this style override the corresponding
|
||||
/// properties in [_IconButtonM3.themeStyleOf] and [_IconButtonM3.defaultStyleOf].
|
||||
/// [MaterialStateProperty]s that resolve to non-null values will similarly
|
||||
/// override the corresponding [MaterialStateProperty]s in [_IconButtonM3.themeStyleOf]
|
||||
/// and [_IconButtonM3.defaultStyleOf].
|
||||
///
|
||||
/// The [style] is only used for Material 3 [IconButton]. If [ThemeData.useMaterial3]
|
||||
/// is set to true, [style] is preferred for icon button customization, and any
|
||||
/// parameters defined in [style] will override the same parameters in [IconButton].
|
||||
///
|
||||
/// For example, if [IconButton]'s [visualDensity] is set to [VisualDensity.standard]
|
||||
/// and [style]'s [visualDensity] is set to [VisualDensity.compact],
|
||||
/// the icon button will have [VisualDensity.compact] to define the button's layout.
|
||||
///
|
||||
/// Null by default.
|
||||
final ButtonStyle? style;
|
||||
|
||||
/// A static convenience method that constructs an icon button
|
||||
/// [ButtonStyle] given simple values. This method is only used for Material 3.
|
||||
///
|
||||
/// The [foregroundColor] color is used to create a [MaterialStateProperty]
|
||||
/// [ButtonStyle.foregroundColor] value. Specify a value for [foregroundColor]
|
||||
/// to specify the color of the button's icons. The [hoverColor], [focusColor]
|
||||
/// and [highlightColor] colors are used to indicate the hover, focus,
|
||||
/// and pressed states. Use [backgroundColor] for the button's background
|
||||
/// fill color. Use [disabledForegroundColor] and [disabledBackgroundColor]
|
||||
/// to specify the button's disabled icon and fill color.
|
||||
///
|
||||
/// Similarly, the [enabledMouseCursor] and [disabledMouseCursor]
|
||||
/// parameters are used to construct [ButtonStyle].mouseCursor.
|
||||
///
|
||||
/// All of the other parameters are either used directly or used to
|
||||
/// create a [MaterialStateProperty] with a single value for all
|
||||
/// states.
|
||||
///
|
||||
/// All parameters default to null, by default this method returns
|
||||
/// a [ButtonStyle] that doesn't override anything.
|
||||
///
|
||||
/// For example, to override the default icon color for a
|
||||
/// [IconButton], as well as its overlay color, with all of the
|
||||
/// standard opacity adjustments for the pressed, focused, and
|
||||
/// hovered states, one could write:
|
||||
///
|
||||
/// ```dart
|
||||
/// IconButton(
|
||||
/// style: IconButton.styleFrom(foregroundColor: Colors.green),
|
||||
/// )
|
||||
/// ```
|
||||
static ButtonStyle styleFrom({
|
||||
Color? foregroundColor,
|
||||
Color? backgroundColor,
|
||||
Color? disabledForegroundColor,
|
||||
Color? disabledBackgroundColor,
|
||||
Color? focusColor,
|
||||
Color? hoverColor,
|
||||
Color? highlightColor,
|
||||
Color? shadowColor,
|
||||
Color? surfaceTintColor,
|
||||
double? elevation,
|
||||
Size? minimumSize,
|
||||
Size? fixedSize,
|
||||
Size? maximumSize,
|
||||
BorderSide? side,
|
||||
OutlinedBorder? shape,
|
||||
EdgeInsetsGeometry? padding,
|
||||
MouseCursor? enabledMouseCursor,
|
||||
MouseCursor? disabledMouseCursor,
|
||||
VisualDensity? visualDensity,
|
||||
MaterialTapTargetSize? tapTargetSize,
|
||||
Duration? animationDuration,
|
||||
bool? enableFeedback,
|
||||
AlignmentGeometry? alignment,
|
||||
InteractiveInkFeatureFactory? splashFactory,
|
||||
}) {
|
||||
final MaterialStateProperty<Color?>? buttonBackgroundColor = (backgroundColor == null && disabledBackgroundColor == null)
|
||||
? null
|
||||
: _IconButtonDefaultBackground(backgroundColor, disabledBackgroundColor);
|
||||
final MaterialStateProperty<Color?>? buttonForegroundColor = (foregroundColor == null && disabledForegroundColor == null)
|
||||
? null
|
||||
: _IconButtonDefaultForeground(foregroundColor, disabledForegroundColor);
|
||||
final MaterialStateProperty<Color?>? overlayColor = (foregroundColor == null && hoverColor == null && focusColor == null && highlightColor == null)
|
||||
? null
|
||||
: _IconButtonDefaultOverlay(foregroundColor, focusColor, hoverColor, highlightColor);
|
||||
final MaterialStateProperty<MouseCursor>? mouseCursor = (enabledMouseCursor == null && disabledMouseCursor == null)
|
||||
? null
|
||||
: _IconButtonDefaultMouseCursor(enabledMouseCursor!, disabledMouseCursor!);
|
||||
|
||||
return ButtonStyle(
|
||||
backgroundColor: buttonBackgroundColor,
|
||||
foregroundColor: buttonForegroundColor,
|
||||
overlayColor: overlayColor,
|
||||
shadowColor: ButtonStyleButton.allOrNull<Color>(shadowColor),
|
||||
surfaceTintColor: ButtonStyleButton.allOrNull<Color>(surfaceTintColor),
|
||||
elevation: ButtonStyleButton.allOrNull<double>(elevation),
|
||||
padding: ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(padding),
|
||||
minimumSize: ButtonStyleButton.allOrNull<Size>(minimumSize),
|
||||
fixedSize: ButtonStyleButton.allOrNull<Size>(fixedSize),
|
||||
maximumSize: ButtonStyleButton.allOrNull<Size>(maximumSize),
|
||||
side: ButtonStyleButton.allOrNull<BorderSide>(side),
|
||||
shape: ButtonStyleButton.allOrNull<OutlinedBorder>(shape),
|
||||
mouseCursor: mouseCursor,
|
||||
visualDensity: visualDensity,
|
||||
tapTargetSize: tapTargetSize,
|
||||
animationDuration: animationDuration,
|
||||
enableFeedback: enableFeedback,
|
||||
alignment: alignment,
|
||||
splashFactory: splashFactory,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
assert(debugCheckHasMaterial(context));
|
||||
final ThemeData theme = Theme.of(context);
|
||||
if (!theme.useMaterial3) {
|
||||
assert(debugCheckHasMaterial(context));
|
||||
}
|
||||
|
||||
Color? currentColor;
|
||||
if (onPressed != null) {
|
||||
currentColor = color;
|
||||
|
@ -321,6 +457,55 @@ class IconButton extends StatelessWidget {
|
|||
final BoxConstraints adjustedConstraints = effectiveVisualDensity.effectiveConstraints(unadjustedConstraints);
|
||||
final double effectiveIconSize = iconSize ?? IconTheme.of(context).size ?? 24.0;
|
||||
|
||||
if (theme.useMaterial3) {
|
||||
final Size? minSize = constraints == null
|
||||
? null
|
||||
: Size(constraints!.minWidth, constraints!.minHeight);
|
||||
final Size? maxSize = constraints == null
|
||||
? null
|
||||
: Size(constraints!.maxWidth, constraints!.maxHeight);
|
||||
|
||||
ButtonStyle adjustedStyle = styleFrom(
|
||||
visualDensity: visualDensity,
|
||||
foregroundColor: color,
|
||||
disabledForegroundColor: disabledColor,
|
||||
focusColor: focusColor,
|
||||
hoverColor: hoverColor,
|
||||
highlightColor: highlightColor,
|
||||
padding: padding,
|
||||
minimumSize: minSize,
|
||||
maximumSize: maxSize,
|
||||
alignment: alignment,
|
||||
enabledMouseCursor: mouseCursor,
|
||||
disabledMouseCursor: mouseCursor,
|
||||
enableFeedback: enableFeedback,
|
||||
);
|
||||
if (style != null) {
|
||||
adjustedStyle = style!.merge(adjustedStyle);
|
||||
}
|
||||
|
||||
Widget iconButton = IconTheme.merge(
|
||||
data: IconThemeData(
|
||||
size: effectiveIconSize,
|
||||
),
|
||||
child: icon,
|
||||
);
|
||||
if (tooltip != null) {
|
||||
iconButton = Tooltip(
|
||||
message: tooltip,
|
||||
child: iconButton,
|
||||
);
|
||||
}
|
||||
return _IconButtonM3(
|
||||
key: key,
|
||||
style: adjustedStyle,
|
||||
onPressed: onPressed,
|
||||
autofocus: autofocus,
|
||||
focusNode: focusNode,
|
||||
child: iconButton,
|
||||
);
|
||||
}
|
||||
|
||||
Widget result = ConstrainedBox(
|
||||
constraints: adjustedConstraints,
|
||||
child: Padding(
|
||||
|
@ -389,3 +574,245 @@ class IconButton extends StatelessWidget {
|
|||
properties.add(DiagnosticsProperty<FocusNode>('focusNode', focusNode, defaultValue: null));
|
||||
}
|
||||
}
|
||||
|
||||
class _IconButtonM3 extends ButtonStyleButton {
|
||||
const _IconButtonM3({
|
||||
super.key,
|
||||
required super.onPressed,
|
||||
super.style,
|
||||
super.focusNode,
|
||||
super.autofocus = false,
|
||||
required Widget super.child,
|
||||
}) : super(
|
||||
onLongPress: null,
|
||||
onHover: null,
|
||||
onFocusChange: null,
|
||||
clipBehavior: Clip.none);
|
||||
|
||||
/// ## Material 3 defaults
|
||||
///
|
||||
/// If [ThemeData.useMaterial3] is set to true the following defaults will
|
||||
/// be used:
|
||||
///
|
||||
/// * `textStyle` - null
|
||||
/// * `backgroundColor` - transparent
|
||||
/// * `foregroundColor`
|
||||
/// * disabled - Theme.colorScheme.onSurface(0.38)
|
||||
/// * others - Theme.colorScheme.onSurfaceVariant
|
||||
/// * `overlayColor`
|
||||
/// * hovered or focused - Theme.colorScheme.onSurfaceVariant(0.08)
|
||||
/// * pressed - Theme.colorScheme.onSurfaceVariant(0.12)
|
||||
/// * others - null
|
||||
/// * `shadowColor` - null
|
||||
/// * `surfaceTintColor` - null
|
||||
/// * `elevation` - 0
|
||||
/// * `padding` - all(8)
|
||||
/// * `minimumSize` - Size(40, 40)
|
||||
/// * `fixedSize` - null
|
||||
/// * `maximumSize` - Size.infinite
|
||||
/// * `side` - null
|
||||
/// * `shape` - StadiumBorder()
|
||||
/// * `mouseCursor`
|
||||
/// * disabled - SystemMouseCursors.basic
|
||||
/// * others - SystemMouseCursors.click
|
||||
/// * `visualDensity` - theme.visualDensity
|
||||
/// * `tapTargetSize` - theme.materialTapTargetSize
|
||||
/// * `animationDuration` - kThemeChangeDuration
|
||||
/// * `enableFeedback` - true
|
||||
/// * `alignment` - Alignment.center
|
||||
/// * `splashFactory` - Theme.splashFactory
|
||||
@override
|
||||
ButtonStyle defaultStyleOf(BuildContext context) {
|
||||
return _TokenDefaultsM3(context);
|
||||
}
|
||||
|
||||
/// Returns null because [IconButton] doesn't have its component theme.
|
||||
@override
|
||||
ButtonStyle? themeStyleOf(BuildContext context) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@immutable
|
||||
class _IconButtonDefaultBackground extends MaterialStateProperty<Color?> {
|
||||
_IconButtonDefaultBackground(this.background, this.disabledBackground);
|
||||
|
||||
final Color? background;
|
||||
final Color? disabledBackground;
|
||||
|
||||
@override
|
||||
Color? resolve(Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.disabled)) {
|
||||
return disabledBackground;
|
||||
}
|
||||
return background;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '{disabled: $disabledBackground, otherwise: $background}';
|
||||
}
|
||||
}
|
||||
|
||||
@immutable
|
||||
class _IconButtonDefaultForeground extends MaterialStateProperty<Color?> {
|
||||
_IconButtonDefaultForeground(this.foregroundColor, this.disabledForegroundColor);
|
||||
|
||||
final Color? foregroundColor;
|
||||
final Color? disabledForegroundColor;
|
||||
|
||||
@override
|
||||
Color? resolve(Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.disabled)) {
|
||||
return disabledForegroundColor;
|
||||
}
|
||||
return foregroundColor;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '{disabled: $disabledForegroundColor, otherwise: $foregroundColor}';
|
||||
}
|
||||
}
|
||||
|
||||
@immutable
|
||||
class _IconButtonDefaultOverlay extends MaterialStateProperty<Color?> {
|
||||
_IconButtonDefaultOverlay(this.foregroundColor, this.focusColor, this.hoverColor, this.highlightColor);
|
||||
|
||||
final Color? foregroundColor;
|
||||
final Color? focusColor;
|
||||
final Color? hoverColor;
|
||||
final Color? highlightColor;
|
||||
|
||||
@override
|
||||
Color? resolve(Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.hovered)) {
|
||||
return hoverColor ?? foregroundColor?.withOpacity(0.08);
|
||||
}
|
||||
if (states.contains(MaterialState.focused)) {
|
||||
return focusColor ?? foregroundColor?.withOpacity(0.08);
|
||||
}
|
||||
if (states.contains(MaterialState.pressed)) {
|
||||
return highlightColor ?? foregroundColor?.withOpacity(0.12);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '{hovered: $hoverColor, focused: $focusColor, pressed: $highlightColor, otherwise: null}';
|
||||
}
|
||||
}
|
||||
|
||||
@immutable
|
||||
class _IconButtonDefaultMouseCursor extends MaterialStateProperty<MouseCursor> with Diagnosticable {
|
||||
_IconButtonDefaultMouseCursor(this.enabledCursor, this.disabledCursor);
|
||||
|
||||
final MouseCursor enabledCursor;
|
||||
final MouseCursor disabledCursor;
|
||||
|
||||
@override
|
||||
MouseCursor resolve(Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.disabled)) {
|
||||
return disabledCursor;
|
||||
}
|
||||
return enabledCursor;
|
||||
}
|
||||
}
|
||||
|
||||
// BEGIN GENERATED TOKEN PROPERTIES
|
||||
|
||||
// Generated code to the end of this file. Do not edit by hand.
|
||||
// These defaults are generated from the Material Design Token
|
||||
// database by the script dev/tools/gen_defaults/bin/gen_defaults.dart.
|
||||
|
||||
// Generated version v0_98
|
||||
class _TokenDefaultsM3 extends ButtonStyle {
|
||||
_TokenDefaultsM3(this.context)
|
||||
: super(
|
||||
animationDuration: kThemeChangeDuration,
|
||||
enableFeedback: true,
|
||||
alignment: Alignment.center,
|
||||
);
|
||||
|
||||
final BuildContext context;
|
||||
late final ColorScheme _colors = Theme.of(context).colorScheme;
|
||||
|
||||
// No default text style
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?>? get backgroundColor =>
|
||||
ButtonStyleButton.allOrNull<Color>(Colors.transparent);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?>? get foregroundColor =>
|
||||
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.disabled)) {
|
||||
return _colors.onSurface.withOpacity(0.38);
|
||||
}
|
||||
return _colors.onSurfaceVariant;
|
||||
});
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?>? get overlayColor =>
|
||||
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.hovered)) {
|
||||
return _colors.onSurfaceVariant.withOpacity(0.08);
|
||||
}
|
||||
if (states.contains(MaterialState.focused)) {
|
||||
return _colors.onSurfaceVariant.withOpacity(0.08);
|
||||
}
|
||||
if (states.contains(MaterialState.pressed)) {
|
||||
return _colors.onSurfaceVariant.withOpacity(0.12);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
// No default shadow color
|
||||
|
||||
// No default surface tint color
|
||||
|
||||
@override
|
||||
MaterialStateProperty<double>? get elevation =>
|
||||
ButtonStyleButton.allOrNull<double>(0.0);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
|
||||
ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(const EdgeInsets.all(8.0));
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get minimumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(const Size(40.0, 40.0));
|
||||
|
||||
// No default fixedSize
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get maximumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(Size.infinite);
|
||||
|
||||
// No default side
|
||||
|
||||
@override
|
||||
MaterialStateProperty<OutlinedBorder>? get shape =>
|
||||
ButtonStyleButton.allOrNull<OutlinedBorder>(const StadiumBorder());
|
||||
|
||||
@override
|
||||
MaterialStateProperty<MouseCursor?>? get mouseCursor =>
|
||||
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.disabled)) {
|
||||
return SystemMouseCursors.basic;
|
||||
}
|
||||
return SystemMouseCursors.click;
|
||||
});
|
||||
|
||||
@override
|
||||
VisualDensity? get visualDensity => Theme.of(context).visualDensity;
|
||||
|
||||
@override
|
||||
MaterialTapTargetSize? get tapTargetSize => Theme.of(context).materialTapTargetSize;
|
||||
|
||||
@override
|
||||
InteractiveInkFeatureFactory? get splashFactory => Theme.of(context).splashFactory;
|
||||
}
|
||||
|
||||
// END GENERATED TOKEN PROPERTIES
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue