Migrate common buttons to Material 3 (#100794)
This commit is contained in:
parent
1755819cb1
commit
c14ca6d321
@ -17,6 +17,7 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
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';
|
||||
@ -77,6 +78,9 @@ Future<void> main(List<String> args) async {
|
||||
tokens['colorsLight'] = _readTokenFile('color_light.json');
|
||||
tokens['colorsDark'] = _readTokenFile('color_dark.json');
|
||||
|
||||
ButtonTemplate('md.comp.elevated-button', '$materialLib/elevated_button.dart', tokens).updateFile();
|
||||
ButtonTemplate('md.comp.outlined-button', '$materialLib/outlined_button.dart', tokens).updateFile();
|
||||
ButtonTemplate('md.comp.text-button', '$materialLib/text_button.dart', tokens).updateFile();
|
||||
CardTemplate('$materialLib/card.dart', tokens).updateFile();
|
||||
DialogTemplate('$materialLib/dialog.dart', tokens).updateFile();
|
||||
FABTemplate('$materialLib/floating_action_button.dart', tokens).updateFile();
|
||||
|
153
dev/tools/gen_defaults/lib/button_template.dart
Normal file
153
dev/tools/gen_defaults/lib/button_template.dart
Normal file
@ -0,0 +1,153 @@
|
||||
// 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 ButtonTemplate extends TokenTemplate {
|
||||
const ButtonTemplate(this.tokenGroup, String fileName, Map<String, dynamic> tokens)
|
||||
: super(fileName, tokens,
|
||||
colorSchemePrefix: '_colors.',
|
||||
);
|
||||
|
||||
final String tokenGroup;
|
||||
|
||||
String _backgroundColor() {
|
||||
if (tokens.containsKey('$tokenGroup.container.color')) {
|
||||
return '''
|
||||
|
||||
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.disabled))
|
||||
return ${componentColor('$tokenGroup.disabled.container')};
|
||||
return ${componentColor('$tokenGroup.container')};
|
||||
})''';
|
||||
}
|
||||
return '''
|
||||
|
||||
ButtonStyleButton.allOrNull<Color>(Colors.transparent)''';
|
||||
}
|
||||
|
||||
String _elevation() {
|
||||
if (tokens.containsKey('$tokenGroup.container.elevation')) {
|
||||
return '''
|
||||
|
||||
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.disabled))
|
||||
return ${elevation("$tokenGroup.disabled.container")};
|
||||
if (states.contains(MaterialState.hovered))
|
||||
return ${elevation("$tokenGroup.hover.container")};
|
||||
if (states.contains(MaterialState.focused))
|
||||
return ${elevation("$tokenGroup.focus.container")};
|
||||
if (states.contains(MaterialState.pressed))
|
||||
return ${elevation("$tokenGroup.pressed.container")};
|
||||
return ${elevation("$tokenGroup.container")};
|
||||
})''';
|
||||
}
|
||||
return '''
|
||||
|
||||
ButtonStyleButton.allOrNull<double>(0.0)''';
|
||||
}
|
||||
|
||||
@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;
|
||||
|
||||
@override
|
||||
MaterialStateProperty<TextStyle?> get textStyle =>
|
||||
MaterialStateProperty.all<TextStyle?>(${textStyle("$tokenGroup.label-text")});
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?>? get backgroundColor =>${_backgroundColor()};
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?>? get foregroundColor =>
|
||||
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.disabled))
|
||||
return ${componentColor('$tokenGroup.disabled.label-text')};
|
||||
return ${componentColor('$tokenGroup.label-text')};
|
||||
});
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?>? get overlayColor =>
|
||||
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.hovered))
|
||||
return ${componentColor('$tokenGroup.hover.state-layer')};
|
||||
if (states.contains(MaterialState.focused))
|
||||
return ${componentColor('$tokenGroup.focus.state-layer')};
|
||||
if (states.contains(MaterialState.pressed))
|
||||
return ${componentColor('$tokenGroup.pressed.state-layer')};
|
||||
return null;
|
||||
});
|
||||
|
||||
${tokens.containsKey("$tokenGroup.container.shadow-color") ? '''
|
||||
@override
|
||||
MaterialStateProperty<Color>? get shadowColor =>
|
||||
ButtonStyleButton.allOrNull<Color>(${color("$tokenGroup.container.shadow-color")});''' : '''
|
||||
// No default shadow color'''}
|
||||
|
||||
${tokens.containsKey("$tokenGroup.container.surface-tint-layer.color") ? '''
|
||||
@override
|
||||
MaterialStateProperty<Color>? get surfaceTintColor =>
|
||||
ButtonStyleButton.allOrNull<Color>(${color("$tokenGroup.container.surface-tint-layer.color")});''' : '''
|
||||
// No default surface tint color'''}
|
||||
|
||||
@override
|
||||
MaterialStateProperty<double>? get elevation =>${_elevation()};
|
||||
|
||||
@override
|
||||
MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
|
||||
ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(_scaledPadding(context));
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get minimumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(const Size(64.0, ${tokens["$tokenGroup.container.height"]}));
|
||||
|
||||
// No default fixedSize
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get maximumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(Size.infinite);
|
||||
|
||||
${tokens.containsKey("$tokenGroup.outline.color") ? '''
|
||||
@override
|
||||
MaterialStateProperty<BorderSide>? get side =>
|
||||
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.disabled))
|
||||
return ${border("$tokenGroup.disabled.outline")};
|
||||
return ${border("$tokenGroup.outline")};
|
||||
});''' : '''
|
||||
// No default side'''}
|
||||
|
||||
@override
|
||||
MaterialStateProperty<OutlinedBorder>? get shape =>
|
||||
ButtonStyleButton.allOrNull<OutlinedBorder>(${shape("$tokenGroup.container")});
|
||||
|
||||
@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;
|
||||
}
|
||||
''';
|
||||
}
|
@ -70,8 +70,8 @@ abstract class TokenTemplate {
|
||||
/// * [componentColor], that provides support for an optional opacity.
|
||||
String color(String colorToken) {
|
||||
return tokens.containsKey(colorToken)
|
||||
? '$colorSchemePrefix${tokens[colorToken]}'
|
||||
: 'null';
|
||||
? '$colorSchemePrefix${tokens[colorToken]}'
|
||||
: 'null';
|
||||
}
|
||||
|
||||
/// Generate a [ColorScheme] color name for the given component's color
|
||||
@ -91,17 +91,25 @@ abstract class TokenTemplate {
|
||||
if (!tokens.containsKey(colorToken))
|
||||
return 'null';
|
||||
String value = color(colorToken);
|
||||
final String tokenOpacity = '$componentToken.opacity';
|
||||
if (tokens.containsKey(tokenOpacity)) {
|
||||
final dynamic opacityValue = tokens[tokenOpacity];
|
||||
final String opacity = opacityValue is double
|
||||
? opacityValue.toString()
|
||||
: tokens[tokens[tokenOpacity]!]!.toString();
|
||||
value += '.withOpacity($opacity)';
|
||||
final String opacityToken = '$componentToken.opacity';
|
||||
if (tokens.containsKey(opacityToken)) {
|
||||
value += '.withOpacity(${opacity(opacityToken)})';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/// Generate the opacity value for the given token.
|
||||
String? opacity(String token) {
|
||||
final dynamic value = tokens[token];
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
if (value is double) {
|
||||
return value.toString();
|
||||
}
|
||||
return tokens[value].toString();
|
||||
}
|
||||
|
||||
/// Generate an elevation value for the given component token.
|
||||
String elevation(String componentToken) {
|
||||
return tokens[tokens['$componentToken.elevation']!]!.toString();
|
||||
@ -135,7 +143,7 @@ abstract class TokenTemplate {
|
||||
return 'null';
|
||||
}
|
||||
final String borderColor = componentColor(componentToken);
|
||||
final double width = tokens['$componentToken.width'] as double;
|
||||
final double width = (tokens['$componentToken.width'] ?? 1.0) as double;
|
||||
return 'BorderSide(color: $borderColor${width != 1.0 ? ", width: $width" : ""})';
|
||||
}
|
||||
|
||||
|
95
examples/api/lib/material/button_style/button_style.0.dart
Normal file
95
examples/api/lib/material/button_style/button_style.0.dart
Normal file
@ -0,0 +1,95 @@
|
||||
// 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 ElevatedButton
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const ButtonApp());
|
||||
}
|
||||
|
||||
class ButtonApp extends StatelessWidget {
|
||||
const ButtonApp({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
theme: ThemeData(colorSchemeSeed: const Color(0xff6750a4), useMaterial3: true),
|
||||
title: 'Button Types',
|
||||
home: const Scaffold(
|
||||
body: ButtonTypesExample(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ButtonTypesExample extends StatelessWidget {
|
||||
const ButtonTypesExample({Key? key}) : super(key: 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({ Key? key, required this.enabled }) : super(key: key);
|
||||
|
||||
final bool enabled;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final VoidCallback? onPressed = enabled ? () {} : null;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: <Widget>[
|
||||
ElevatedButton(onPressed: onPressed, child: const Text('Elevated')),
|
||||
|
||||
// Use an ElevatedButton with specific style to implement the
|
||||
// 'Filled' type.
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
// Foreground color
|
||||
onPrimary: Theme.of(context).colorScheme.onPrimary,
|
||||
// Background color
|
||||
primary: Theme.of(context).colorScheme.primary,
|
||||
).copyWith(elevation: ButtonStyleButton.allOrNull(0.0)),
|
||||
onPressed: onPressed,
|
||||
child: const Text('Filled'),
|
||||
),
|
||||
|
||||
// Use an ElevatedButton with specific style to implement the
|
||||
// 'Filled Tonal' type.
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
// Foreground color
|
||||
onPrimary: Theme.of(context).colorScheme.onSecondaryContainer,
|
||||
// Background color
|
||||
primary: Theme.of(context).colorScheme.secondaryContainer,
|
||||
).copyWith(elevation: ButtonStyleButton.allOrNull(0.0)),
|
||||
onPressed: onPressed,
|
||||
child: const Text('Filled Tonal'),
|
||||
),
|
||||
|
||||
OutlinedButton(onPressed: onPressed, child: const Text('Outlined')),
|
||||
|
||||
TextButton(onPressed: onPressed, child: const Text('Text')),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -91,6 +91,27 @@ import 'theme_data.dart';
|
||||
/// home: MyAppHome(),
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// ## Material 3 button types
|
||||
///
|
||||
/// Material Design 3 specifies five types of common buttons. Flutter provides
|
||||
/// support for these using the following button classes:
|
||||
/// <style>table,td,th { border-collapse: collapse; padding: 0.45em; } td { border: 1px solid }</style>
|
||||
///
|
||||
/// | Type | Flutter implementation |
|
||||
/// | :----------- | :---------------------- |
|
||||
/// | Elevated | [ElevatedButton] |
|
||||
/// | Filled | Styled [ElevatedButton] |
|
||||
/// | Filled Tonal | Styled [ElevatedButton] |
|
||||
/// | Outlined | [OutlinedButton] |
|
||||
/// | Text | [TextButton] |
|
||||
///
|
||||
/// {@tool dartpad}
|
||||
/// This sample shows how to create each of the Material 3 button types with Flutter.
|
||||
///
|
||||
/// ** See code in examples/api/lib/material/button_style/button_style.0.dart **
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [TextButtonTheme], the theme for [TextButton]s.
|
||||
@ -105,6 +126,7 @@ class ButtonStyle with Diagnosticable {
|
||||
this.foregroundColor,
|
||||
this.overlayColor,
|
||||
this.shadowColor,
|
||||
this.surfaceTintColor,
|
||||
this.elevation,
|
||||
this.padding,
|
||||
this.minimumSize,
|
||||
@ -150,6 +172,11 @@ class ButtonStyle with Diagnosticable {
|
||||
/// [ThemeData.applyElevationOverlayColor].
|
||||
final MaterialStateProperty<Color?>? shadowColor;
|
||||
|
||||
/// The surface tint color of the button's [Material].
|
||||
///
|
||||
/// See [Material.surfaceTintColor] for more details.
|
||||
final MaterialStateProperty<Color?>? surfaceTintColor;
|
||||
|
||||
/// The elevation of the button's [Material].
|
||||
final MaterialStateProperty<double?>? elevation;
|
||||
|
||||
@ -267,6 +294,7 @@ class ButtonStyle with Diagnosticable {
|
||||
MaterialStateProperty<Color?>? foregroundColor,
|
||||
MaterialStateProperty<Color?>? overlayColor,
|
||||
MaterialStateProperty<Color?>? shadowColor,
|
||||
MaterialStateProperty<Color?>? surfaceTintColor,
|
||||
MaterialStateProperty<double?>? elevation,
|
||||
MaterialStateProperty<EdgeInsetsGeometry?>? padding,
|
||||
MaterialStateProperty<Size?>? minimumSize,
|
||||
@ -288,6 +316,7 @@ class ButtonStyle with Diagnosticable {
|
||||
foregroundColor: foregroundColor ?? this.foregroundColor,
|
||||
overlayColor: overlayColor ?? this.overlayColor,
|
||||
shadowColor: shadowColor ?? this.shadowColor,
|
||||
surfaceTintColor: surfaceTintColor ?? this.surfaceTintColor,
|
||||
elevation: elevation ?? this.elevation,
|
||||
padding: padding ?? this.padding,
|
||||
minimumSize: minimumSize ?? this.minimumSize,
|
||||
@ -319,6 +348,7 @@ class ButtonStyle with Diagnosticable {
|
||||
foregroundColor: foregroundColor ?? style.foregroundColor,
|
||||
overlayColor: overlayColor ?? style.overlayColor,
|
||||
shadowColor: shadowColor ?? style.shadowColor,
|
||||
surfaceTintColor: surfaceTintColor ?? style.surfaceTintColor,
|
||||
elevation: elevation ?? style.elevation,
|
||||
padding: padding ?? style.padding,
|
||||
minimumSize: minimumSize ?? style.minimumSize,
|
||||
@ -343,6 +373,7 @@ class ButtonStyle with Diagnosticable {
|
||||
foregroundColor,
|
||||
overlayColor,
|
||||
shadowColor,
|
||||
surfaceTintColor,
|
||||
elevation,
|
||||
padding,
|
||||
minimumSize,
|
||||
@ -371,6 +402,7 @@ class ButtonStyle with Diagnosticable {
|
||||
&& other.foregroundColor == foregroundColor
|
||||
&& other.overlayColor == overlayColor
|
||||
&& other.shadowColor == shadowColor
|
||||
&& other.surfaceTintColor == surfaceTintColor
|
||||
&& other.elevation == elevation
|
||||
&& other.padding == padding
|
||||
&& other.minimumSize == minimumSize
|
||||
@ -395,6 +427,7 @@ class ButtonStyle with Diagnosticable {
|
||||
properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('foregroundColor', foregroundColor, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('overlayColor', overlayColor, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('shadowColor', shadowColor, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('surfaceTintColor', surfaceTintColor, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<MaterialStateProperty<double?>>('elevation', elevation, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<MaterialStateProperty<EdgeInsetsGeometry?>>('padding', padding, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<MaterialStateProperty<Size?>>('minimumSize', minimumSize, defaultValue: null));
|
||||
@ -421,6 +454,7 @@ class ButtonStyle with Diagnosticable {
|
||||
foregroundColor: _lerpProperties<Color?>(a?.foregroundColor, b?.foregroundColor, t, Color.lerp),
|
||||
overlayColor: _lerpProperties<Color?>(a?.overlayColor, b?.overlayColor, t, Color.lerp),
|
||||
shadowColor: _lerpProperties<Color?>(a?.shadowColor, b?.shadowColor, t, Color.lerp),
|
||||
surfaceTintColor: _lerpProperties<Color?>(a?.surfaceTintColor, b?.surfaceTintColor, t, Color.lerp),
|
||||
elevation: _lerpProperties<double?>(a?.elevation, b?.elevation, t, lerpDouble),
|
||||
padding: _lerpProperties<EdgeInsetsGeometry?>(a?.padding, b?.padding, t, EdgeInsetsGeometry.lerp),
|
||||
minimumSize: _lerpProperties<Size?>(a?.minimumSize, b?.minimumSize, t, Size.lerp),
|
||||
|
@ -247,6 +247,7 @@ class _ButtonStyleState extends State<ButtonStyleButton> with MaterialStateMixin
|
||||
Color? resolvedBackgroundColor = resolve<Color?>((ButtonStyle? style) => style?.backgroundColor);
|
||||
final Color? resolvedForegroundColor = resolve<Color?>((ButtonStyle? style) => style?.foregroundColor);
|
||||
final Color? resolvedShadowColor = resolve<Color?>((ButtonStyle? style) => style?.shadowColor);
|
||||
final Color? resolvedSurfaceTintColor = resolve<Color?>((ButtonStyle? style) => style?.surfaceTintColor);
|
||||
final EdgeInsetsGeometry? resolvedPadding = resolve<EdgeInsetsGeometry?>((ButtonStyle? style) => style?.padding);
|
||||
final Size? resolvedMinimumSize = resolve<Size?>((ButtonStyle? style) => style?.minimumSize);
|
||||
final Size? resolvedFixedSize = resolve<Size?>((ButtonStyle? style) => style?.fixedSize);
|
||||
@ -343,6 +344,7 @@ class _ButtonStyleState extends State<ButtonStyleButton> with MaterialStateMixin
|
||||
shape: resolvedShape!.copyWith(side: resolvedSide),
|
||||
color: resolvedBackgroundColor,
|
||||
shadowColor: resolvedShadowColor,
|
||||
surfaceTintColor: resolvedSurfaceTintColor,
|
||||
type: resolvedBackgroundColor == null ? MaterialType.transparency : MaterialType.button,
|
||||
animationDuration: resolvedAnimationDuration,
|
||||
clipBehavior: widget.clipBehavior,
|
||||
|
@ -148,6 +148,7 @@ class ElevatedButton extends ButtonStyleButton {
|
||||
Color? onPrimary,
|
||||
Color? onSurface,
|
||||
Color? shadowColor,
|
||||
Color? surfaceTintColor,
|
||||
double? elevation,
|
||||
TextStyle? textStyle,
|
||||
EdgeInsetsGeometry? padding,
|
||||
@ -187,6 +188,7 @@ class ElevatedButton extends ButtonStyleButton {
|
||||
foregroundColor: foregroundColor,
|
||||
overlayColor: overlayColor,
|
||||
shadowColor: ButtonStyleButton.allOrNull<Color>(shadowColor),
|
||||
surfaceTintColor: ButtonStyleButton.allOrNull<Color>(surfaceTintColor),
|
||||
elevation: elevationValue,
|
||||
padding: ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(padding),
|
||||
minimumSize: ButtonStyleButton.allOrNull<Size>(minimumSize),
|
||||
@ -228,6 +230,8 @@ class ElevatedButton extends ButtonStyleButton {
|
||||
/// The color of the [ButtonStyle.textStyle] is not used, the
|
||||
/// [ButtonStyle.foregroundColor] color is used instead.
|
||||
///
|
||||
/// ## Material 2 defaults
|
||||
///
|
||||
/// * `textStyle` - Theme.textTheme.button
|
||||
/// * `backgroundColor`
|
||||
/// * disabled - Theme.colorScheme.onSurface(0.12)
|
||||
@ -245,7 +249,7 @@ class ElevatedButton extends ButtonStyleButton {
|
||||
/// * hovered or focused - 4
|
||||
/// * pressed - 8
|
||||
/// * `padding`
|
||||
/// * textScaleFactor <= 1 - horizontal(16)
|
||||
/// * `textScaleFactor <= 1` - horizontal(16)
|
||||
/// * `1 < textScaleFactor <= 2` - lerp(horizontal(16), horizontal(8))
|
||||
/// * `2 < textScaleFactor <= 3` - lerp(horizontal(8), horizontal(4))
|
||||
/// * `3 < textScaleFactor` - horizontal(4)
|
||||
@ -276,38 +280,75 @@ class ElevatedButton extends ButtonStyleButton {
|
||||
/// outline, is null. That means that the outline is defined by the button
|
||||
/// shape's [OutlinedBorder.side]. Typically the default value of an
|
||||
/// [OutlinedBorder]'s side is [BorderSide.none], so an outline is not drawn.
|
||||
///
|
||||
/// ## Material 3 defaults
|
||||
///
|
||||
/// If [ThemeData.useMaterial3] is set to true the following defaults will
|
||||
/// be used:
|
||||
///
|
||||
/// * `textStyle` - Theme.textTheme.labelLarge
|
||||
/// * `backgroundColor`
|
||||
/// * disabled - Theme.colorScheme.onSurface(0.12)
|
||||
/// * others - Theme.colorScheme.surface
|
||||
/// * `foregroundColor`
|
||||
/// * disabled - Theme.colorScheme.onSurface(0.38)
|
||||
/// * others - Theme.colorScheme.primary
|
||||
/// * `overlayColor`
|
||||
/// * hovered - Theme.colorScheme.primary(0.08)
|
||||
/// * focused or pressed - Theme.colorScheme.primary(0.12)
|
||||
/// * `shadowColor` - Theme.colorScheme.shadow
|
||||
/// * `surfaceTintColor` - Theme.colorScheme.surfaceTint
|
||||
/// * `elevation`
|
||||
/// * disabled - 0
|
||||
/// * default - 1
|
||||
/// * hovered - 3
|
||||
/// * focused or pressed - 1
|
||||
/// * `padding`
|
||||
/// * `textScaleFactor <= 1` - horizontal(16)
|
||||
/// * `1 < textScaleFactor <= 2` - lerp(horizontal(16), horizontal(8))
|
||||
/// * `2 < textScaleFactor <= 3` - lerp(horizontal(8), horizontal(4))
|
||||
/// * `3 < textScaleFactor` - horizontal(4)
|
||||
/// * `minimumSize` - Size(64, 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) {
|
||||
final ThemeData theme = Theme.of(context);
|
||||
final ColorScheme colorScheme = theme.colorScheme;
|
||||
|
||||
final EdgeInsetsGeometry scaledPadding = ButtonStyleButton.scaledPadding(
|
||||
const EdgeInsets.symmetric(horizontal: 16),
|
||||
const EdgeInsets.symmetric(horizontal: 8),
|
||||
const EdgeInsets.symmetric(horizontal: 4),
|
||||
MediaQuery.maybeOf(context)?.textScaleFactor ?? 1,
|
||||
);
|
||||
|
||||
return styleFrom(
|
||||
primary: colorScheme.primary,
|
||||
onPrimary: colorScheme.onPrimary,
|
||||
onSurface: colorScheme.onSurface,
|
||||
shadowColor: theme.shadowColor,
|
||||
elevation: 2,
|
||||
textStyle: theme.textTheme.button,
|
||||
padding: scaledPadding,
|
||||
minimumSize: const Size(64, 36),
|
||||
maximumSize: Size.infinite,
|
||||
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))),
|
||||
enabledMouseCursor: SystemMouseCursors.click,
|
||||
disabledMouseCursor: SystemMouseCursors.basic,
|
||||
visualDensity: theme.visualDensity,
|
||||
tapTargetSize: theme.materialTapTargetSize,
|
||||
animationDuration: kThemeChangeDuration,
|
||||
enableFeedback: true,
|
||||
alignment: Alignment.center,
|
||||
splashFactory: theme.useMaterial3 ? theme.splashFactory : InkRipple.splashFactory,
|
||||
);
|
||||
return Theme.of(context).useMaterial3
|
||||
? _TokenDefaultsM3(context)
|
||||
: styleFrom(
|
||||
primary: colorScheme.primary,
|
||||
onPrimary: colorScheme.onPrimary,
|
||||
onSurface: colorScheme.onSurface,
|
||||
shadowColor: theme.shadowColor,
|
||||
elevation: 2,
|
||||
textStyle: theme.textTheme.button,
|
||||
padding: _scaledPadding(context),
|
||||
minimumSize: const Size(64, 36),
|
||||
maximumSize: Size.infinite,
|
||||
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))),
|
||||
enabledMouseCursor: SystemMouseCursors.click,
|
||||
disabledMouseCursor: SystemMouseCursors.basic,
|
||||
visualDensity: theme.visualDensity,
|
||||
tapTargetSize: theme.materialTapTargetSize,
|
||||
animationDuration: kThemeChangeDuration,
|
||||
enableFeedback: true,
|
||||
alignment: Alignment.center,
|
||||
splashFactory: InkRipple.splashFactory,
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns the [ElevatedButtonThemeData.style] of the closest
|
||||
@ -318,6 +359,15 @@ class ElevatedButton extends ButtonStyleButton {
|
||||
}
|
||||
}
|
||||
|
||||
EdgeInsetsGeometry _scaledPadding(BuildContext context) {
|
||||
return ButtonStyleButton.scaledPadding(
|
||||
const EdgeInsets.symmetric(horizontal: 16),
|
||||
const EdgeInsets.symmetric(horizontal: 8),
|
||||
const EdgeInsets.symmetric(horizontal: 4),
|
||||
MediaQuery.maybeOf(context)?.textScaleFactor ?? 1,
|
||||
);
|
||||
}
|
||||
|
||||
@immutable
|
||||
class _ElevatedButtonDefaultBackground extends MaterialStateProperty<Color?> with Diagnosticable {
|
||||
_ElevatedButtonDefaultBackground(this.primary, this.onSurface);
|
||||
@ -457,3 +507,115 @@ class _ElevatedButtonWithIconChild extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 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_92
|
||||
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;
|
||||
|
||||
@override
|
||||
MaterialStateProperty<TextStyle?> get textStyle =>
|
||||
MaterialStateProperty.all<TextStyle?>(Theme.of(context).textTheme.labelLarge);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?>? get backgroundColor =>
|
||||
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.disabled))
|
||||
return _colors.onSurface.withOpacity(0.12);
|
||||
return _colors.surface;
|
||||
});
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?>? get foregroundColor =>
|
||||
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.disabled))
|
||||
return _colors.onSurface.withOpacity(0.38);
|
||||
return _colors.primary;
|
||||
});
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?>? get overlayColor =>
|
||||
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.hovered))
|
||||
return _colors.primary.withOpacity(0.08);
|
||||
if (states.contains(MaterialState.focused))
|
||||
return _colors.primary.withOpacity(0.12);
|
||||
if (states.contains(MaterialState.pressed))
|
||||
return _colors.primary.withOpacity(0.12);
|
||||
return null;
|
||||
});
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color>? get shadowColor =>
|
||||
ButtonStyleButton.allOrNull<Color>(_colors.shadow);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color>? get surfaceTintColor =>
|
||||
ButtonStyleButton.allOrNull<Color>(_colors.surfaceTint);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<double>? get elevation =>
|
||||
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.disabled))
|
||||
return 0.0;
|
||||
if (states.contains(MaterialState.hovered))
|
||||
return 3.0;
|
||||
if (states.contains(MaterialState.focused))
|
||||
return 1.0;
|
||||
if (states.contains(MaterialState.pressed))
|
||||
return 1.0;
|
||||
return 1.0;
|
||||
});
|
||||
|
||||
@override
|
||||
MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
|
||||
ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(_scaledPadding(context));
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get minimumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(const Size(64.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
|
||||
|
@ -146,6 +146,7 @@ class OutlinedButton extends ButtonStyleButton {
|
||||
Color? onSurface,
|
||||
Color? backgroundColor,
|
||||
Color? shadowColor,
|
||||
Color? surfaceTintColor,
|
||||
double? elevation,
|
||||
TextStyle? textStyle,
|
||||
EdgeInsetsGeometry? padding,
|
||||
@ -179,6 +180,7 @@ class OutlinedButton extends ButtonStyleButton {
|
||||
backgroundColor: ButtonStyleButton.allOrNull<Color>(backgroundColor),
|
||||
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),
|
||||
@ -219,6 +221,8 @@ class OutlinedButton extends ButtonStyleButton {
|
||||
/// The color of the [ButtonStyle.textStyle] is not used, the
|
||||
/// [ButtonStyle.foregroundColor] is used instead.
|
||||
///
|
||||
/// ## Material 2 defaults
|
||||
///
|
||||
/// * `textStyle` - Theme.textTheme.button
|
||||
/// * `backgroundColor` - transparent
|
||||
/// * `foregroundColor`
|
||||
@ -248,41 +252,75 @@ class OutlinedButton extends ButtonStyleButton {
|
||||
/// * `enableFeedback` - true
|
||||
/// * `alignment` - Alignment.center
|
||||
/// * `splashFactory` - InkRipple.splashFactory
|
||||
///
|
||||
/// ## Material 3 defaults
|
||||
///
|
||||
/// If [ThemeData.useMaterial3] is set to true the following defaults will
|
||||
/// be used:
|
||||
///
|
||||
/// * `textStyle` - Theme.textTheme.labelLarge
|
||||
/// * `backgroundColor` - transparent
|
||||
/// * `foregroundColor`
|
||||
/// * disabled - Theme.colorScheme.onSurface(0.38)
|
||||
/// * others - Theme.colorScheme.primary
|
||||
/// * `overlayColor`
|
||||
/// * hovered - Theme.colorScheme.primary(0.08)
|
||||
/// * focused or pressed - Theme.colorScheme.primary(0.12)
|
||||
/// * others - null
|
||||
/// * `shadowColor` - null
|
||||
/// * `surfaceTintColor` - null
|
||||
/// * `elevation` - 0
|
||||
/// * `padding`
|
||||
/// * `textScaleFactor <= 1` - horizontal(16)
|
||||
/// * `1 < textScaleFactor <= 2` - lerp(horizontal(16), horizontal(8))
|
||||
/// * `2 < textScaleFactor <= 3` - lerp(horizontal(8), horizontal(4))
|
||||
/// * `3 < textScaleFactor` - horizontal(4)
|
||||
/// * `minimumSize` - Size(64, 40)
|
||||
/// * `fixedSize` - null
|
||||
/// * `maximumSize` - Size.infinite
|
||||
/// * `side`
|
||||
/// * disabled - BorderSide(color: Theme.colorScheme.onSurface(0.12))
|
||||
/// * others - BorderSide(color: Theme.colorScheme.outline)
|
||||
/// * `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) {
|
||||
final ThemeData theme = Theme.of(context);
|
||||
final ColorScheme colorScheme = theme.colorScheme;
|
||||
|
||||
final EdgeInsetsGeometry scaledPadding = ButtonStyleButton.scaledPadding(
|
||||
const EdgeInsets.symmetric(horizontal: 16),
|
||||
const EdgeInsets.symmetric(horizontal: 8),
|
||||
const EdgeInsets.symmetric(horizontal: 4),
|
||||
MediaQuery.maybeOf(context)?.textScaleFactor ?? 1,
|
||||
);
|
||||
|
||||
return styleFrom(
|
||||
primary: colorScheme.primary,
|
||||
onSurface: colorScheme.onSurface,
|
||||
backgroundColor: Colors.transparent,
|
||||
shadowColor: theme.shadowColor,
|
||||
elevation: 0,
|
||||
textStyle: theme.textTheme.button,
|
||||
padding: scaledPadding,
|
||||
minimumSize: const Size(64, 36),
|
||||
maximumSize: Size.infinite,
|
||||
side: BorderSide(
|
||||
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.12),
|
||||
),
|
||||
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))),
|
||||
enabledMouseCursor: SystemMouseCursors.click,
|
||||
disabledMouseCursor: SystemMouseCursors.basic,
|
||||
visualDensity: theme.visualDensity,
|
||||
tapTargetSize: theme.materialTapTargetSize,
|
||||
animationDuration: kThemeChangeDuration,
|
||||
enableFeedback: true,
|
||||
alignment: Alignment.center,
|
||||
splashFactory: theme.useMaterial3 ? theme.splashFactory : InkRipple.splashFactory,
|
||||
);
|
||||
return Theme.of(context).useMaterial3
|
||||
? _TokenDefaultsM3(context)
|
||||
: styleFrom(
|
||||
primary: colorScheme.primary,
|
||||
onSurface: colorScheme.onSurface,
|
||||
backgroundColor: Colors.transparent,
|
||||
shadowColor: theme.shadowColor,
|
||||
elevation: 0,
|
||||
textStyle: theme.textTheme.button,
|
||||
padding: _scaledPadding(context),
|
||||
minimumSize: const Size(64, 36),
|
||||
maximumSize: Size.infinite,
|
||||
side: BorderSide(
|
||||
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.12),
|
||||
),
|
||||
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))),
|
||||
enabledMouseCursor: SystemMouseCursors.click,
|
||||
disabledMouseCursor: SystemMouseCursors.basic,
|
||||
visualDensity: theme.visualDensity,
|
||||
tapTargetSize: theme.materialTapTargetSize,
|
||||
animationDuration: kThemeChangeDuration,
|
||||
enableFeedback: true,
|
||||
alignment: Alignment.center,
|
||||
splashFactory: InkRipple.splashFactory,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -291,6 +329,15 @@ class OutlinedButton extends ButtonStyleButton {
|
||||
}
|
||||
}
|
||||
|
||||
EdgeInsetsGeometry _scaledPadding(BuildContext context) {
|
||||
return ButtonStyleButton.scaledPadding(
|
||||
const EdgeInsets.symmetric(horizontal: 16),
|
||||
const EdgeInsets.symmetric(horizontal: 8),
|
||||
const EdgeInsets.symmetric(horizontal: 4),
|
||||
MediaQuery.maybeOf(context)?.textScaleFactor ?? 1,
|
||||
);
|
||||
}
|
||||
|
||||
@immutable
|
||||
class _OutlinedButtonDefaultForeground extends MaterialStateProperty<Color?> with Diagnosticable {
|
||||
_OutlinedButtonDefaultForeground(this.primary, this.onSurface);
|
||||
@ -382,3 +429,103 @@ class _OutlinedButtonWithIconChild extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 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_92
|
||||
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;
|
||||
|
||||
@override
|
||||
MaterialStateProperty<TextStyle?> get textStyle =>
|
||||
MaterialStateProperty.all<TextStyle?>(Theme.of(context).textTheme.labelLarge);
|
||||
|
||||
@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.primary;
|
||||
});
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?>? get overlayColor =>
|
||||
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.hovered))
|
||||
return _colors.primary.withOpacity(0.08);
|
||||
if (states.contains(MaterialState.focused))
|
||||
return _colors.primary.withOpacity(0.12);
|
||||
if (states.contains(MaterialState.pressed))
|
||||
return _colors.primary.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>(_scaledPadding(context));
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get minimumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(const Size(64.0, 40.0));
|
||||
|
||||
// No default fixedSize
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get maximumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(Size.infinite);
|
||||
|
||||
@override
|
||||
MaterialStateProperty<BorderSide>? get side =>
|
||||
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.disabled))
|
||||
return BorderSide(color: _colors.onSurface.withOpacity(0.12));
|
||||
return BorderSide(color: _colors.outline);
|
||||
});
|
||||
|
||||
@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
|
||||
|
@ -147,6 +147,7 @@ class TextButton extends ButtonStyleButton {
|
||||
Color? onSurface,
|
||||
Color? backgroundColor,
|
||||
Color? shadowColor,
|
||||
Color? surfaceTintColor,
|
||||
double? elevation,
|
||||
TextStyle? textStyle,
|
||||
EdgeInsetsGeometry? padding,
|
||||
@ -180,6 +181,7 @@ class TextButton extends ButtonStyleButton {
|
||||
foregroundColor: foregroundColor,
|
||||
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),
|
||||
@ -223,6 +225,8 @@ class TextButton extends ButtonStyleButton {
|
||||
/// The color of the [ButtonStyle.textStyle] is not used, the
|
||||
/// [ButtonStyle.foregroundColor] color is used instead.
|
||||
///
|
||||
/// ## Material 2 defaults
|
||||
///
|
||||
/// * `textStyle` - Theme.textTheme.button
|
||||
/// * `backgroundColor` - transparent
|
||||
/// * `foregroundColor`
|
||||
@ -264,38 +268,70 @@ class TextButton extends ButtonStyleButton {
|
||||
/// outline, is null. That means that the outline is defined by the button
|
||||
/// shape's [OutlinedBorder.side]. Typically the default value of an
|
||||
/// [OutlinedBorder]'s side is [BorderSide.none], so an outline is not drawn.
|
||||
///
|
||||
/// ## Material 3 defaults
|
||||
///
|
||||
/// If [ThemeData.useMaterial3] is set to true the following defaults will
|
||||
/// be used:
|
||||
///
|
||||
/// * `textStyle` - Theme.textTheme.labelLarge
|
||||
/// * `backgroundColor` - transparent
|
||||
/// * `foregroundColor`
|
||||
/// * disabled - Theme.colorScheme.onSurface(0.38)
|
||||
/// * others - Theme.colorScheme.primary
|
||||
/// * `overlayColor`
|
||||
/// * hovered - Theme.colorScheme.primary(0.08)
|
||||
/// * focused or pressed - Theme.colorScheme.primary(0.12)
|
||||
/// * others - null
|
||||
/// * `shadowColor` - null
|
||||
/// * `surfaceTintColor` - null
|
||||
/// * `elevation` - 0
|
||||
/// * `padding`
|
||||
/// * `textScaleFactor <= 1` - all(8)
|
||||
/// * `1 < textScaleFactor <= 2` - lerp(all(8), horizontal(8))
|
||||
/// * `2 < textScaleFactor <= 3` - lerp(horizontal(8), horizontal(4))
|
||||
/// * `3 < textScaleFactor` - horizontal(4)
|
||||
/// * `minimumSize` - Size(64, 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) {
|
||||
final ThemeData theme = Theme.of(context);
|
||||
final ColorScheme colorScheme = theme.colorScheme;
|
||||
|
||||
final EdgeInsetsGeometry scaledPadding = ButtonStyleButton.scaledPadding(
|
||||
const EdgeInsets.all(8),
|
||||
const EdgeInsets.symmetric(horizontal: 8),
|
||||
const EdgeInsets.symmetric(horizontal: 4),
|
||||
MediaQuery.maybeOf(context)?.textScaleFactor ?? 1,
|
||||
);
|
||||
|
||||
return styleFrom(
|
||||
primary: colorScheme.primary,
|
||||
onSurface: colorScheme.onSurface,
|
||||
backgroundColor: Colors.transparent,
|
||||
shadowColor: theme.shadowColor,
|
||||
elevation: 0,
|
||||
textStyle: theme.textTheme.button,
|
||||
padding: scaledPadding,
|
||||
minimumSize: const Size(64, 36),
|
||||
maximumSize: Size.infinite,
|
||||
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))),
|
||||
enabledMouseCursor: SystemMouseCursors.click,
|
||||
disabledMouseCursor: SystemMouseCursors.basic,
|
||||
visualDensity: theme.visualDensity,
|
||||
tapTargetSize: theme.materialTapTargetSize,
|
||||
animationDuration: kThemeChangeDuration,
|
||||
enableFeedback: true,
|
||||
alignment: Alignment.center,
|
||||
splashFactory: theme.useMaterial3 ? theme.splashFactory : InkRipple.splashFactory,
|
||||
);
|
||||
return Theme.of(context).useMaterial3
|
||||
? _TokenDefaultsM3(context)
|
||||
: styleFrom(
|
||||
primary: colorScheme.primary,
|
||||
onSurface: colorScheme.onSurface,
|
||||
backgroundColor: Colors.transparent,
|
||||
shadowColor: theme.shadowColor,
|
||||
elevation: 0,
|
||||
textStyle: theme.textTheme.button,
|
||||
padding: _scaledPadding(context),
|
||||
minimumSize: const Size(64, 36),
|
||||
maximumSize: Size.infinite,
|
||||
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))),
|
||||
enabledMouseCursor: SystemMouseCursors.click,
|
||||
disabledMouseCursor: SystemMouseCursors.basic,
|
||||
visualDensity: theme.visualDensity,
|
||||
tapTargetSize: theme.materialTapTargetSize,
|
||||
animationDuration: kThemeChangeDuration,
|
||||
enableFeedback: true,
|
||||
alignment: Alignment.center,
|
||||
splashFactory: InkRipple.splashFactory,
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns the [TextButtonThemeData.style] of the closest
|
||||
@ -306,6 +342,15 @@ class TextButton extends ButtonStyleButton {
|
||||
}
|
||||
}
|
||||
|
||||
EdgeInsetsGeometry _scaledPadding(BuildContext context) {
|
||||
return ButtonStyleButton.scaledPadding(
|
||||
const EdgeInsets.all(8),
|
||||
const EdgeInsets.symmetric(horizontal: 8),
|
||||
const EdgeInsets.symmetric(horizontal: 4),
|
||||
MediaQuery.maybeOf(context)?.textScaleFactor ?? 1,
|
||||
);
|
||||
}
|
||||
|
||||
@immutable
|
||||
class _TextButtonDefaultForeground extends MaterialStateProperty<Color?> {
|
||||
_TextButtonDefaultForeground(this.primary, this.onSurface);
|
||||
@ -424,3 +469,97 @@ class _TextButtonWithIconChild extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 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_92
|
||||
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;
|
||||
|
||||
@override
|
||||
MaterialStateProperty<TextStyle?> get textStyle =>
|
||||
MaterialStateProperty.all<TextStyle?>(Theme.of(context).textTheme.labelLarge);
|
||||
|
||||
@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.primary;
|
||||
});
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Color?>? get overlayColor =>
|
||||
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.hovered))
|
||||
return _colors.primary.withOpacity(0.08);
|
||||
if (states.contains(MaterialState.focused))
|
||||
return _colors.primary.withOpacity(0.12);
|
||||
if (states.contains(MaterialState.pressed))
|
||||
return _colors.primary.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>(_scaledPadding(context));
|
||||
|
||||
@override
|
||||
MaterialStateProperty<Size>? get minimumSize =>
|
||||
ButtonStyleButton.allOrNull<Size>(const Size(64.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
|
||||
|
@ -1170,21 +1170,25 @@ class ThemeData with Diagnosticable {
|
||||
/// {@endtemplate}
|
||||
final VisualDensity visualDensity;
|
||||
|
||||
/// A temporary flag used to opt-in to new Material 3 features.
|
||||
/// A temporary flag used to opt-in to Material 3 features.
|
||||
///
|
||||
/// If true, then components that have been migrated to Material 3 will
|
||||
/// start using new colors, typography and other features of Material 3.
|
||||
/// use new colors, typography and other features of Material 3.
|
||||
/// If false, they will use the Material 2 look and feel.
|
||||
///
|
||||
/// If a [ThemeData] is constructed with [useMaterial3] set to true, then
|
||||
/// some properties will get special defaults. However, just copying a [ThemeData]
|
||||
/// with [useMaterial3] set to true will not change any of these properties in the
|
||||
/// resulting [ThemeData]. These properties are:
|
||||
/// | Property | [useMaterial3] default | fallback default |
|
||||
/// |:---|:---|:---|
|
||||
/// | [typography] | [Typography.material2021] | [Typography.material2014] |
|
||||
/// | [splashFactory] | [InkSparkle]* | [InkSplash] |
|
||||
/// *if and only if the target platform is Android and the app is not running on the web.
|
||||
/// <style>table,td,th { border-collapse: collapse; padding: 0.45em; } td { border: 1px solid }</style>
|
||||
///
|
||||
/// | Property | Material 3 default | Fallback default |
|
||||
/// | :-------------- | :--------------------------- | :------------------------ |
|
||||
/// | [typography] | [Typography.material2021] | [Typography.material2014] |
|
||||
/// | [splashFactory] | [InkSparkle]* or [InkRipple] | [InkSplash] |
|
||||
///
|
||||
/// \* if and only if the target platform is Android and the app is not
|
||||
/// running on the web, otherwise it will fallback to [InkRipple].
|
||||
///
|
||||
/// During the migration to Material 3, turning this on may yield
|
||||
/// inconsistent look and feel in your app. Some components will be migrated
|
||||
@ -1201,12 +1205,15 @@ class ThemeData with Diagnosticable {
|
||||
/// * [AlertDialog]
|
||||
/// * [Card]
|
||||
/// * [Dialog]
|
||||
/// * [ElevatedButton]
|
||||
/// * [FloatingActionButton]
|
||||
/// * [Material]
|
||||
/// * [NavigationBar]
|
||||
/// * [NavigationRail]
|
||||
/// * [OutlinedButton]
|
||||
/// * [StretchingOverscrollIndicator], replacing the
|
||||
/// [GlowingOverscrollIndicator]
|
||||
/// * [TextButton]
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
|
@ -20,6 +20,8 @@ void main() {
|
||||
expect(style.backgroundColor, null);
|
||||
expect(style.foregroundColor, null);
|
||||
expect(style.overlayColor, null);
|
||||
expect(style.shadowColor, null);
|
||||
expect(style.surfaceTintColor, null);
|
||||
expect(style.elevation, null);
|
||||
expect(style.padding, null);
|
||||
expect(style.minimumSize, null);
|
||||
@ -53,10 +55,12 @@ void main() {
|
||||
backgroundColor: MaterialStateProperty.all<Color>(const Color(0xfffffff1)),
|
||||
foregroundColor: MaterialStateProperty.all<Color>(const Color(0xfffffff2)),
|
||||
overlayColor: MaterialStateProperty.all<Color>(const Color(0xfffffff3)),
|
||||
shadowColor: MaterialStateProperty.all<Color>(const Color(0xfffffff4)),
|
||||
surfaceTintColor: MaterialStateProperty.all<Color>(const Color(0xfffffff5)),
|
||||
elevation: MaterialStateProperty.all<double>(1.5),
|
||||
padding: MaterialStateProperty.all<EdgeInsets>(const EdgeInsets.all(1.0)),
|
||||
minimumSize: MaterialStateProperty.all<Size>(const Size(1.0, 2.0)),
|
||||
side: MaterialStateProperty.all<BorderSide>(const BorderSide(width: 4.0, color: Color(0xfffffff4))),
|
||||
side: MaterialStateProperty.all<BorderSide>(const BorderSide(width: 4.0, color: Color(0xfffffff6))),
|
||||
maximumSize: MaterialStateProperty.all<Size>(const Size(100.0, 200.0)),
|
||||
shape: MaterialStateProperty.all<OutlinedBorder>(const StadiumBorder()),
|
||||
mouseCursor: MaterialStateProperty.all<MouseCursor>(SystemMouseCursors.forbidden),
|
||||
@ -75,11 +79,13 @@ void main() {
|
||||
'backgroundColor: MaterialStateProperty.all(Color(0xfffffff1))',
|
||||
'foregroundColor: MaterialStateProperty.all(Color(0xfffffff2))',
|
||||
'overlayColor: MaterialStateProperty.all(Color(0xfffffff3))',
|
||||
'shadowColor: MaterialStateProperty.all(Color(0xfffffff4))',
|
||||
'surfaceTintColor: MaterialStateProperty.all(Color(0xfffffff5))',
|
||||
'elevation: MaterialStateProperty.all(1.5)',
|
||||
'padding: MaterialStateProperty.all(EdgeInsets.all(1.0))',
|
||||
'minimumSize: MaterialStateProperty.all(Size(1.0, 2.0))',
|
||||
'maximumSize: MaterialStateProperty.all(Size(100.0, 200.0))',
|
||||
'side: MaterialStateProperty.all(BorderSide(Color(0xfffffff4), 4.0, BorderStyle.solid))',
|
||||
'side: MaterialStateProperty.all(BorderSide(Color(0xfffffff6), 4.0, BorderStyle.solid))',
|
||||
'shape: MaterialStateProperty.all(StadiumBorder(BorderSide(Color(0xff000000), 0.0, BorderStyle.none)))',
|
||||
'mouseCursor: MaterialStateProperty.all(SystemMouseCursor(forbidden))',
|
||||
'tapTargetSize: shrinkWrap',
|
||||
@ -93,6 +99,8 @@ void main() {
|
||||
final MaterialStateProperty<Color> backgroundColor = MaterialStateProperty.all<Color>(const Color(0xfffffff1));
|
||||
final MaterialStateProperty<Color> foregroundColor = MaterialStateProperty.all<Color>(const Color(0xfffffff2));
|
||||
final MaterialStateProperty<Color> overlayColor = MaterialStateProperty.all<Color>(const Color(0xfffffff3));
|
||||
final MaterialStateProperty<Color> shadowColor = MaterialStateProperty.all<Color>(const Color(0xfffffff4));
|
||||
final MaterialStateProperty<Color> surfaceTintColor = MaterialStateProperty.all<Color>(const Color(0xfffffff5));
|
||||
final MaterialStateProperty<double> elevation = MaterialStateProperty.all<double>(1);
|
||||
final MaterialStateProperty<EdgeInsets> padding = MaterialStateProperty.all<EdgeInsets>(const EdgeInsets.all(1));
|
||||
final MaterialStateProperty<Size> minimumSize = MaterialStateProperty.all<Size>(const Size(1, 2));
|
||||
@ -111,6 +119,8 @@ void main() {
|
||||
backgroundColor: backgroundColor,
|
||||
foregroundColor: foregroundColor,
|
||||
overlayColor: overlayColor,
|
||||
shadowColor: shadowColor,
|
||||
surfaceTintColor: surfaceTintColor,
|
||||
elevation: elevation,
|
||||
padding: padding,
|
||||
minimumSize: minimumSize,
|
||||
@ -132,6 +142,8 @@ void main() {
|
||||
backgroundColor: backgroundColor,
|
||||
foregroundColor: foregroundColor,
|
||||
overlayColor: overlayColor,
|
||||
shadowColor: shadowColor,
|
||||
surfaceTintColor: surfaceTintColor,
|
||||
elevation: elevation,
|
||||
padding: padding,
|
||||
minimumSize: minimumSize,
|
||||
|
@ -14,11 +14,13 @@ import '../widgets/semantics_tester.dart';
|
||||
void main() {
|
||||
testWidgets('ElevatedButton, ElevatedButton.icon defaults', (WidgetTester tester) async {
|
||||
const ColorScheme colorScheme = ColorScheme.light();
|
||||
final ThemeData theme = ThemeData.from(colorScheme: colorScheme);
|
||||
final bool material3 = theme.useMaterial3;
|
||||
|
||||
// Enabled ElevatedButton
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData.from(colorScheme: colorScheme),
|
||||
theme: theme,
|
||||
home: Center(
|
||||
child: ElevatedButton(
|
||||
onPressed: () { },
|
||||
@ -39,11 +41,13 @@ void main() {
|
||||
expect(material.borderOnForeground, true);
|
||||
expect(material.borderRadius, null);
|
||||
expect(material.clipBehavior, Clip.none);
|
||||
expect(material.color, colorScheme.primary);
|
||||
expect(material.elevation, 2);
|
||||
expect(material.color, material3 ? colorScheme.onPrimary : colorScheme.primary);
|
||||
expect(material.elevation, material3 ? 1: 2);
|
||||
expect(material.shadowColor, const Color(0xff000000));
|
||||
expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
|
||||
expect(material.textStyle!.color, colorScheme.onPrimary);
|
||||
expect(material.shape, material3
|
||||
? const StadiumBorder()
|
||||
: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
|
||||
expect(material.textStyle!.color, material3 ? colorScheme.primary : colorScheme.onPrimary);
|
||||
expect(material.textStyle!.fontFamily, 'Roboto');
|
||||
expect(material.textStyle!.fontSize, 14);
|
||||
expect(material.textStyle!.fontWeight, FontWeight.w500);
|
||||
@ -56,8 +60,13 @@ void main() {
|
||||
final TestGesture gesture = await tester.startGesture(center);
|
||||
await tester.pump(); // start the splash animation
|
||||
await tester.pump(const Duration(milliseconds: 100)); // splash is underway
|
||||
final RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
|
||||
expect(inkFeatures, paints..circle(color: colorScheme.onPrimary.withAlpha(0x3d))); // splash color is onPrimary(0.24)
|
||||
|
||||
// Material 3 uses the InkSparkle which uses a shader, so we can't capture
|
||||
// the effect with paint methods.
|
||||
if (!material3) {
|
||||
final RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
|
||||
expect(inkFeatures, paints..circle(color: colorScheme.onPrimary.withOpacity(0.24)));
|
||||
}
|
||||
|
||||
// Only elevation changes when enabled and pressed.
|
||||
material = tester.widget<Material>(buttonMaterial);
|
||||
@ -65,11 +74,13 @@ void main() {
|
||||
expect(material.borderOnForeground, true);
|
||||
expect(material.borderRadius, null);
|
||||
expect(material.clipBehavior, Clip.none);
|
||||
expect(material.color, colorScheme.primary);
|
||||
expect(material.elevation, 8);
|
||||
expect(material.color, material3 ? colorScheme.onPrimary : colorScheme.primary);
|
||||
expect(material.elevation, material3 ? 1 : 8);
|
||||
expect(material.shadowColor, const Color(0xff000000));
|
||||
expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
|
||||
expect(material.textStyle!.color, colorScheme.onPrimary);
|
||||
expect(material.shape, material3
|
||||
? const StadiumBorder()
|
||||
: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
|
||||
expect(material.textStyle!.color, material3 ? colorScheme.primary : colorScheme.onPrimary);
|
||||
expect(material.textStyle!.fontFamily, 'Roboto');
|
||||
expect(material.textStyle!.fontSize, 14);
|
||||
expect(material.textStyle!.fontWeight, FontWeight.w500);
|
||||
@ -82,7 +93,7 @@ void main() {
|
||||
final Key iconButtonKey = UniqueKey();
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData.from(colorScheme: colorScheme),
|
||||
theme: theme,
|
||||
home: Center(
|
||||
child: ElevatedButton.icon(
|
||||
key: iconButtonKey,
|
||||
@ -104,11 +115,13 @@ void main() {
|
||||
expect(material.borderOnForeground, true);
|
||||
expect(material.borderRadius, null);
|
||||
expect(material.clipBehavior, Clip.none);
|
||||
expect(material.color, colorScheme.primary);
|
||||
expect(material.elevation, 2);
|
||||
expect(material.color, material3 ? colorScheme.onPrimary : colorScheme.primary);
|
||||
expect(material.elevation, material3? 1 : 2);
|
||||
expect(material.shadowColor, const Color(0xff000000));
|
||||
expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
|
||||
expect(material.textStyle!.color, colorScheme.onPrimary);
|
||||
expect(material.shape, material3
|
||||
? const StadiumBorder()
|
||||
: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
|
||||
expect(material.textStyle!.color, material3 ? colorScheme.primary : colorScheme.onPrimary);
|
||||
expect(material.textStyle!.fontFamily, 'Roboto');
|
||||
expect(material.textStyle!.fontSize, 14);
|
||||
expect(material.textStyle!.fontWeight, FontWeight.w500);
|
||||
@ -117,7 +130,7 @@ void main() {
|
||||
// Disabled ElevatedButton
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData.from(colorScheme: colorScheme),
|
||||
theme: theme,
|
||||
home: const Center(
|
||||
child: ElevatedButton(
|
||||
onPressed: null,
|
||||
@ -138,7 +151,9 @@ void main() {
|
||||
expect(material.color, colorScheme.onSurface.withOpacity(0.12));
|
||||
expect(material.elevation, 0.0);
|
||||
expect(material.shadowColor, const Color(0xff000000));
|
||||
expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
|
||||
expect(material.shape, material3
|
||||
? const StadiumBorder()
|
||||
: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
|
||||
expect(material.textStyle!.color, colorScheme.onSurface.withOpacity(0.38));
|
||||
expect(material.textStyle!.fontFamily, 'Roboto');
|
||||
expect(material.textStyle!.fontSize, 14);
|
||||
@ -770,6 +785,9 @@ void main() {
|
||||
Future<void> buildTest(VisualDensity visualDensity, {bool useText = false}) async {
|
||||
return tester.pumpWidget(
|
||||
MaterialApp(
|
||||
// Test was setup using fonts from Material 2, so make sure we always
|
||||
// test against englishLike2014.
|
||||
theme: ThemeData(textTheme: Typography.englishLike2014),
|
||||
home: Directionality(
|
||||
textDirection: TextDirection.rtl,
|
||||
child: Center(
|
||||
@ -961,7 +979,15 @@ void main() {
|
||||
testWidgets(testName, (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData.from(colorScheme: const ColorScheme.light()),
|
||||
theme: ThemeData(
|
||||
colorScheme: const ColorScheme.light(),
|
||||
// Force Material 2 defaults for the typography and size
|
||||
// default values as the test was designed against these settings.
|
||||
textTheme: Typography.englishLike2014,
|
||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||
style: ElevatedButton.styleFrom(minimumSize: const Size(64, 36)),
|
||||
),
|
||||
),
|
||||
home: Builder(
|
||||
builder: (BuildContext context) {
|
||||
return MediaQuery(
|
||||
@ -1137,7 +1163,7 @@ void main() {
|
||||
|
||||
Widget buildFrame({ required bool enabled }) {
|
||||
return MaterialApp(
|
||||
theme: ThemeData.from(colorScheme: colorScheme),
|
||||
theme: ThemeData.from(colorScheme: colorScheme, useMaterial3: false),
|
||||
home: Center(
|
||||
child: ElevatedButton(
|
||||
onPressed: enabled ? () { } : null,
|
||||
@ -1181,23 +1207,29 @@ void main() {
|
||||
const Color borderColor = Color(0xff4caf50);
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData.from(colorScheme: const ColorScheme.light()),
|
||||
theme: ThemeData(colorScheme: const ColorScheme.light(), textTheme: Typography.englishLike2014, useMaterial3: false),
|
||||
home: Center(
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(16)),
|
||||
side: BorderSide(width: 4, color: borderColor),
|
||||
side: BorderSide(width: 10, color: borderColor),
|
||||
),
|
||||
minimumSize: const Size(64, 36),
|
||||
),
|
||||
onPressed: () { },
|
||||
onPressed: () {},
|
||||
child: const Text('button'),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.byType(ElevatedButton), paints ..path(strokeWidth: 4) ..drrect(color: borderColor));
|
||||
expect(find.byType(ElevatedButton), paints ..drrect(
|
||||
// Outer and inner rect that give the outline a width of 10.
|
||||
outer: RRect.fromLTRBR(0.0, 0.0, 116.0, 36.0, const Radius.circular(16)),
|
||||
inner: RRect.fromLTRBR(10.0, 10.0, 106.0, 26.0, const Radius.circular(16 - 10)),
|
||||
color: borderColor)
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Fixed size ElevatedButtons', (WidgetTester tester) async {
|
||||
@ -1261,8 +1293,8 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
// Default splashFactory (from Theme.of().splashFactory), one splash circle drawn.
|
||||
await tester.pumpWidget(buildFrame());
|
||||
// InkRipple.splashFactory, one splash circle drawn.
|
||||
await tester.pumpWidget(buildFrame(splashFactory: InkRipple.splashFactory));
|
||||
{
|
||||
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
||||
final MaterialInkController material = Material.of(tester.element(find.text('test')))!;
|
||||
@ -1386,6 +1418,7 @@ void main() {
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(textTheme: Typography.englishLike2014),
|
||||
home: Scaffold(
|
||||
body: Center(
|
||||
child: Column(
|
||||
|
@ -14,11 +14,13 @@ import '../widgets/semantics_tester.dart';
|
||||
void main() {
|
||||
testWidgets('OutlinedButton, OutlinedButton.icon defaults', (WidgetTester tester) async {
|
||||
const ColorScheme colorScheme = ColorScheme.light();
|
||||
final ThemeData theme = ThemeData.from(colorScheme: colorScheme);
|
||||
final bool material3 = theme.useMaterial3;
|
||||
|
||||
// Enabled OutlinedButton
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData.from(colorScheme: colorScheme),
|
||||
theme: theme,
|
||||
home: Center(
|
||||
child: OutlinedButton(
|
||||
onPressed: () { },
|
||||
@ -40,12 +42,14 @@ void main() {
|
||||
expect(material.clipBehavior, Clip.none);
|
||||
expect(material.color, Colors.transparent);
|
||||
expect(material.elevation, 0.0);
|
||||
expect(material.shadowColor, const Color(0xff000000));
|
||||
expect(material.shadowColor, material3 ? null : const Color(0xff000000));
|
||||
|
||||
expect(material.shape, isInstanceOf<RoundedRectangleBorder>());
|
||||
RoundedRectangleBorder materialShape = material.shape! as RoundedRectangleBorder;
|
||||
expect(materialShape.side, BorderSide(color: colorScheme.onSurface.withOpacity(0.12)));
|
||||
expect(materialShape.borderRadius, const BorderRadius.all(Radius.circular(4.0)));
|
||||
expect(material.shape, material3
|
||||
? StadiumBorder(side: BorderSide(color: colorScheme.outline))
|
||||
: RoundedRectangleBorder(
|
||||
side: BorderSide(color: colorScheme.onSurface.withOpacity(0.12)),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(4))
|
||||
));
|
||||
|
||||
expect(material.textStyle!.color, colorScheme.primary);
|
||||
expect(material.textStyle!.fontFamily, 'Roboto');
|
||||
@ -60,8 +64,13 @@ void main() {
|
||||
final TestGesture gesture = await tester.startGesture(center);
|
||||
await tester.pump(); // start the splash animation
|
||||
await tester.pump(const Duration(milliseconds: 100)); // splash is underway
|
||||
final RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
|
||||
expect(inkFeatures, paints..circle(color: colorScheme.primary.withAlpha(0x1f))); // splash color is primary(0.12)
|
||||
|
||||
// Material 3 uses the InkSparkle which uses a shader, so we can't capture
|
||||
// the effect with paint methods.
|
||||
if (!material3) {
|
||||
final RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
|
||||
expect(inkFeatures, paints..circle(color: colorScheme.primary.withOpacity(0.12)));
|
||||
}
|
||||
|
||||
await gesture.up();
|
||||
await tester.pumpAndSettle();
|
||||
@ -73,12 +82,14 @@ void main() {
|
||||
expect(material.clipBehavior, Clip.none);
|
||||
expect(material.color, Colors.transparent);
|
||||
expect(material.elevation, 0.0);
|
||||
expect(material.shadowColor, const Color(0xff000000));
|
||||
expect(material.shadowColor, material3 ? null : const Color(0xff000000));
|
||||
|
||||
expect(material.shape, isInstanceOf<RoundedRectangleBorder>());
|
||||
materialShape = material.shape! as RoundedRectangleBorder;
|
||||
expect(materialShape.side, BorderSide(color: colorScheme.onSurface.withOpacity(0.12)));
|
||||
expect(materialShape.borderRadius, const BorderRadius.all(Radius.circular(4.0)));
|
||||
expect(material.shape, material3
|
||||
? StadiumBorder(side: BorderSide(color: colorScheme.outline))
|
||||
: RoundedRectangleBorder(
|
||||
side: BorderSide(color: colorScheme.onSurface.withOpacity(0.12)),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(4))
|
||||
));
|
||||
|
||||
expect(material.textStyle!.color, colorScheme.primary);
|
||||
expect(material.textStyle!.fontFamily, 'Roboto');
|
||||
@ -90,7 +101,7 @@ void main() {
|
||||
final Key iconButtonKey = UniqueKey();
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData.from(colorScheme: colorScheme),
|
||||
theme: theme,
|
||||
home: Center(
|
||||
child: OutlinedButton.icon(
|
||||
key: iconButtonKey,
|
||||
@ -114,12 +125,14 @@ void main() {
|
||||
expect(material.clipBehavior, Clip.none);
|
||||
expect(material.color, Colors.transparent);
|
||||
expect(material.elevation, 0.0);
|
||||
expect(material.shadowColor, const Color(0xff000000));
|
||||
expect(material.shadowColor, material3 ? null : const Color(0xff000000));
|
||||
|
||||
expect(material.shape, isInstanceOf<RoundedRectangleBorder>());
|
||||
materialShape = material.shape! as RoundedRectangleBorder;
|
||||
expect(materialShape.side, BorderSide(color: colorScheme.onSurface.withOpacity(0.12)));
|
||||
expect(materialShape.borderRadius, const BorderRadius.all(Radius.circular(4.0)));
|
||||
expect(material.shape, material3
|
||||
? StadiumBorder(side: BorderSide(color: colorScheme.outline))
|
||||
: RoundedRectangleBorder(
|
||||
side: BorderSide(color: colorScheme.onSurface.withOpacity(0.12)),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(4))
|
||||
));
|
||||
|
||||
expect(material.textStyle!.color, colorScheme.primary);
|
||||
expect(material.textStyle!.fontFamily, 'Roboto');
|
||||
@ -130,7 +143,7 @@ void main() {
|
||||
// Disabled OutlinedButton
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData.from(colorScheme: colorScheme),
|
||||
theme: theme,
|
||||
home: const Center(
|
||||
child: OutlinedButton(
|
||||
onPressed: null,
|
||||
@ -147,12 +160,14 @@ void main() {
|
||||
expect(material.clipBehavior, Clip.none);
|
||||
expect(material.color, Colors.transparent);
|
||||
expect(material.elevation, 0.0);
|
||||
expect(material.shadowColor, const Color(0xff000000));
|
||||
expect(material.shadowColor, material3 ? null : const Color(0xff000000));
|
||||
|
||||
expect(material.shape, isInstanceOf<RoundedRectangleBorder>());
|
||||
materialShape = material.shape! as RoundedRectangleBorder;
|
||||
expect(materialShape.side, BorderSide(color: colorScheme.onSurface.withOpacity(0.12)));
|
||||
expect(materialShape.borderRadius, const BorderRadius.all(Radius.circular(4.0)));
|
||||
expect(material.shape, material3
|
||||
? StadiumBorder(side: BorderSide(color: colorScheme.onSurface.withOpacity(0.12)))
|
||||
: RoundedRectangleBorder(
|
||||
side: BorderSide(color: colorScheme.onSurface.withOpacity(0.12)),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(4))
|
||||
));
|
||||
|
||||
expect(material.textStyle!.color, colorScheme.onSurface.withOpacity(0.38));
|
||||
expect(material.textStyle!.fontFamily, 'Roboto');
|
||||
@ -531,6 +546,10 @@ void main() {
|
||||
child: OutlinedButton(
|
||||
style: ButtonStyle(
|
||||
side: MaterialStateProperty.resolveWith<BorderSide>(getBorderSide),
|
||||
// Test assumes a rounded rect for the shape
|
||||
shape: ButtonStyleButton.allOrNull(
|
||||
const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4)))
|
||||
),
|
||||
),
|
||||
onPressed: () {},
|
||||
focusNode: focusNode,
|
||||
@ -808,13 +827,14 @@ void main() {
|
||||
return Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Theme(
|
||||
data: ThemeData(materialTapTargetSize: MaterialTapTargetSize.shrinkWrap),
|
||||
data: ThemeData(materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, textTheme: Typography.englishLike2014),
|
||||
child: Container(
|
||||
alignment: Alignment.topLeft,
|
||||
child: OutlinedButton(
|
||||
style: OutlinedButton.styleFrom(
|
||||
shape: const RoundedRectangleBorder(), // default border radius is 0
|
||||
backgroundColor: fillColor,
|
||||
minimumSize: const Size(64, 36),
|
||||
).copyWith(
|
||||
side: MaterialStateProperty.resolveWith<BorderSide>((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.disabled))
|
||||
@ -964,20 +984,24 @@ void main() {
|
||||
|
||||
testWidgets('OutlinedButton scales textScaleFactor', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: MediaQuery(
|
||||
data: const MediaQueryData(),
|
||||
child: Center(
|
||||
child: OutlinedButton(
|
||||
style: ButtonStyle(
|
||||
// Specifying minimumSize to mimic the original minimumSize for
|
||||
// RaisedButton so that the corresponding button size matches
|
||||
// the original version of this test.
|
||||
minimumSize: MaterialStateProperty.all<Size>(const Size(88, 36)),
|
||||
Theme(
|
||||
// Force Material 2 typography.
|
||||
data: ThemeData(textTheme: Typography.englishLike2014),
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: MediaQuery(
|
||||
data: const MediaQueryData(),
|
||||
child: Center(
|
||||
child: OutlinedButton(
|
||||
style: ButtonStyle(
|
||||
// Specifying minimumSize to mimic the original minimumSize for
|
||||
// RaisedButton so that the corresponding button size matches
|
||||
// the original version of this test.
|
||||
minimumSize: MaterialStateProperty.all<Size>(const Size(88, 36)),
|
||||
),
|
||||
onPressed: () {},
|
||||
child: const Text('ABC'),
|
||||
),
|
||||
onPressed: () {},
|
||||
child: const Text('ABC'),
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -989,20 +1013,24 @@ void main() {
|
||||
|
||||
// textScaleFactor expands text, but not button.
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: MediaQuery(
|
||||
data: const MediaQueryData(textScaleFactor: 1.3),
|
||||
child: Center(
|
||||
child: OutlinedButton(
|
||||
style: ButtonStyle(
|
||||
// Specifying minimumSize to mimic the original minimumSize for
|
||||
// RaisedButton so that the corresponding button size matches
|
||||
// the original version of this test.
|
||||
minimumSize: MaterialStateProperty.all<Size>(const Size(88, 36)),
|
||||
Theme(
|
||||
// Force Material 2 typography.
|
||||
data: ThemeData(textTheme: Typography.englishLike2014),
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: MediaQuery(
|
||||
data: const MediaQueryData(textScaleFactor: 1.3),
|
||||
child: Center(
|
||||
child: OutlinedButton(
|
||||
style: ButtonStyle(
|
||||
// Specifying minimumSize to mimic the original minimumSize for
|
||||
// RaisedButton so that the corresponding button size matches
|
||||
// the original version of this test.
|
||||
minimumSize: MaterialStateProperty.all<Size>(const Size(88, 36)),
|
||||
),
|
||||
onPressed: () {},
|
||||
child: const Text('ABC'),
|
||||
),
|
||||
onPressed: () {},
|
||||
child: const Text('ABC'),
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -1017,14 +1045,18 @@ void main() {
|
||||
|
||||
// Set text scale large enough to expand text and button.
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: MediaQuery(
|
||||
data: const MediaQueryData(textScaleFactor: 3.0),
|
||||
child: Center(
|
||||
child: OutlinedButton(
|
||||
onPressed: () {},
|
||||
child: const Text('ABC'),
|
||||
Theme(
|
||||
// Force Material 2 typography.
|
||||
data: ThemeData(textTheme: Typography.englishLike2014),
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: MediaQuery(
|
||||
data: const MediaQueryData(textScaleFactor: 3.0),
|
||||
child: Center(
|
||||
child: OutlinedButton(
|
||||
onPressed: () {},
|
||||
child: const Text('ABC'),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -1039,7 +1071,6 @@ void main() {
|
||||
expect(tester.getSize(find.byType(Text)).height, equals(42.0));
|
||||
});
|
||||
|
||||
|
||||
testWidgets('OutlinedButton onPressed and onLongPress callbacks are distinctly recognized', (WidgetTester tester) async {
|
||||
bool didPressButton = false;
|
||||
bool didLongPressButton = false;
|
||||
@ -1078,11 +1109,15 @@ void main() {
|
||||
Future<void> buildTest(VisualDensity visualDensity, {bool useText = false}) async {
|
||||
return tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(textTheme: Typography.englishLike2014),
|
||||
home: Directionality(
|
||||
textDirection: TextDirection.rtl,
|
||||
child: Center(
|
||||
child: OutlinedButton(
|
||||
style: ButtonStyle(visualDensity: visualDensity),
|
||||
style: ButtonStyle(
|
||||
visualDensity: visualDensity,
|
||||
minimumSize: ButtonStyleButton.allOrNull(const Size(64, 36)),
|
||||
),
|
||||
key: key,
|
||||
onPressed: () {},
|
||||
child: useText
|
||||
@ -1203,7 +1238,15 @@ void main() {
|
||||
testWidgets(testName, (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData.from(colorScheme: const ColorScheme.light()),
|
||||
theme: ThemeData(
|
||||
colorScheme: const ColorScheme.light(),
|
||||
// Force Material 2 defaults for the typography and size
|
||||
// default values as the test was designed against these settings.
|
||||
textTheme: Typography.englishLike2014,
|
||||
outlinedButtonTheme: OutlinedButtonThemeData(
|
||||
style: OutlinedButton.styleFrom(minimumSize: const Size(64, 36)),
|
||||
),
|
||||
),
|
||||
home: Builder(
|
||||
builder: (BuildContext context) {
|
||||
return MediaQuery(
|
||||
@ -1434,8 +1477,8 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
// Default splashFactory (from Theme.of().splashFactory), one splash circle drawn.
|
||||
await tester.pumpWidget(buildFrame());
|
||||
// InkRipple.splashFactory, one splash circle drawn.
|
||||
await tester.pumpWidget(buildFrame(splashFactory: InkRipple.splashFactory));
|
||||
{
|
||||
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
||||
final MaterialInkController material = Material.of(tester.element(find.text('test')))!;
|
||||
@ -1559,6 +1602,7 @@ void main() {
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(textTheme: Typography.englishLike2014),
|
||||
home: Scaffold(
|
||||
body: Center(
|
||||
child: Column(
|
||||
|
@ -14,11 +14,13 @@ import '../widgets/semantics_tester.dart';
|
||||
void main() {
|
||||
testWidgets('TextButton, TextButton.icon defaults', (WidgetTester tester) async {
|
||||
const ColorScheme colorScheme = ColorScheme.light();
|
||||
final ThemeData theme = ThemeData.from(colorScheme: colorScheme);
|
||||
final bool material3 = theme.useMaterial3;
|
||||
|
||||
// Enabled TextButton
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData.from(colorScheme: colorScheme),
|
||||
theme: theme,
|
||||
home: Center(
|
||||
child: TextButton(
|
||||
onPressed: () { },
|
||||
@ -40,8 +42,10 @@ void main() {
|
||||
expect(material.clipBehavior, Clip.none);
|
||||
expect(material.color, Colors.transparent);
|
||||
expect(material.elevation, 0.0);
|
||||
expect(material.shadowColor, const Color(0xff000000));
|
||||
expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))));
|
||||
expect(material.shadowColor, material3 ? null : const Color(0xff000000));
|
||||
expect(material.shape, material3
|
||||
? const StadiumBorder()
|
||||
: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
|
||||
expect(material.textStyle!.color, colorScheme.primary);
|
||||
expect(material.textStyle!.fontFamily, 'Roboto');
|
||||
expect(material.textStyle!.fontSize, 14);
|
||||
@ -55,8 +59,13 @@ void main() {
|
||||
final TestGesture gesture = await tester.startGesture(center);
|
||||
await tester.pump(); // start the splash animation
|
||||
await tester.pump(const Duration(milliseconds: 100)); // splash is underway
|
||||
final RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
|
||||
expect(inkFeatures, paints..circle(color: colorScheme.primary.withAlpha(0x1f))); // splash color is primary(0.12)
|
||||
|
||||
// Material 3 uses the InkSparkle which uses a shader, so we can't capture
|
||||
// the effect with paint methods.
|
||||
if (!material3) {
|
||||
final RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
|
||||
expect(inkFeatures, paints..circle(color: colorScheme.primary.withOpacity(0.12)));
|
||||
}
|
||||
|
||||
await gesture.up();
|
||||
await tester.pumpAndSettle();
|
||||
@ -68,8 +77,10 @@ void main() {
|
||||
expect(material.clipBehavior, Clip.none);
|
||||
expect(material.color, Colors.transparent);
|
||||
expect(material.elevation, 0.0);
|
||||
expect(material.shadowColor, const Color(0xff000000));
|
||||
expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))));
|
||||
expect(material.shadowColor, material3 ? null : const Color(0xff000000));
|
||||
expect(material.shape, material3
|
||||
? const StadiumBorder()
|
||||
: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
|
||||
expect(material.textStyle!.color, colorScheme.primary);
|
||||
expect(material.textStyle!.fontFamily, 'Roboto');
|
||||
expect(material.textStyle!.fontSize, 14);
|
||||
@ -80,7 +91,7 @@ void main() {
|
||||
final Key iconButtonKey = UniqueKey();
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData.from(colorScheme: colorScheme),
|
||||
theme: theme,
|
||||
home: Center(
|
||||
child: TextButton.icon(
|
||||
key: iconButtonKey,
|
||||
@ -104,8 +115,10 @@ void main() {
|
||||
expect(material.clipBehavior, Clip.none);
|
||||
expect(material.color, Colors.transparent);
|
||||
expect(material.elevation, 0.0);
|
||||
expect(material.shadowColor, const Color(0xff000000));
|
||||
expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))));
|
||||
expect(material.shadowColor, material3 ? null : const Color(0xff000000));
|
||||
expect(material.shape, material3
|
||||
? const StadiumBorder()
|
||||
: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
|
||||
expect(material.textStyle!.color, colorScheme.primary);
|
||||
expect(material.textStyle!.fontFamily, 'Roboto');
|
||||
expect(material.textStyle!.fontSize, 14);
|
||||
@ -115,7 +128,7 @@ void main() {
|
||||
// Disabled TextButton
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData.from(colorScheme: colorScheme),
|
||||
theme: theme,
|
||||
home: const Center(
|
||||
child: TextButton(
|
||||
onPressed: null,
|
||||
@ -132,8 +145,10 @@ void main() {
|
||||
expect(material.clipBehavior, Clip.none);
|
||||
expect(material.color, Colors.transparent);
|
||||
expect(material.elevation, 0.0);
|
||||
expect(material.shadowColor, const Color(0xff000000));
|
||||
expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))));
|
||||
expect(material.shadowColor, material3 ? null : const Color(0xff000000));
|
||||
expect(material.shape, material3
|
||||
? const StadiumBorder()
|
||||
: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
|
||||
expect(material.textStyle!.color, colorScheme.onSurface.withOpacity(0.38));
|
||||
expect(material.textStyle!.fontFamily, 'Roboto');
|
||||
expect(material.textStyle!.fontSize, 14);
|
||||
@ -517,14 +532,18 @@ void main() {
|
||||
|
||||
testWidgets('Does TextButton scale with font scale changes', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: MediaQuery(
|
||||
data: const MediaQueryData(),
|
||||
child: Center(
|
||||
child: TextButton(
|
||||
onPressed: () { },
|
||||
child: const Text('ABC'),
|
||||
Theme(
|
||||
// Force Material 2 typography.
|
||||
data: ThemeData(textTheme: Typography.englishLike2014),
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: MediaQuery(
|
||||
data: const MediaQueryData(),
|
||||
child: Center(
|
||||
child: TextButton(
|
||||
onPressed: () { },
|
||||
child: const Text('ABC'),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -536,14 +555,18 @@ void main() {
|
||||
|
||||
// textScaleFactor expands text, but not button.
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: MediaQuery(
|
||||
data: const MediaQueryData(textScaleFactor: 1.3),
|
||||
child: Center(
|
||||
child: TextButton(
|
||||
onPressed: () { },
|
||||
child: const Text('ABC'),
|
||||
Theme(
|
||||
// Force Material 2 typography.
|
||||
data: ThemeData(textTheme: Typography.englishLike2014),
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: MediaQuery(
|
||||
data: const MediaQueryData(textScaleFactor: 1.3),
|
||||
child: Center(
|
||||
child: TextButton(
|
||||
onPressed: () { },
|
||||
child: const Text('ABC'),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -559,14 +582,18 @@ void main() {
|
||||
|
||||
// Set text scale large enough to expand text and button.
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: MediaQuery(
|
||||
data: const MediaQueryData(textScaleFactor: 3.0),
|
||||
child: Center(
|
||||
child: TextButton(
|
||||
onPressed: () { },
|
||||
child: const Text('ABC'),
|
||||
Theme(
|
||||
// Force Material 2 typography.
|
||||
data: ThemeData(textTheme: Typography.englishLike2014),
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: MediaQuery(
|
||||
data: const MediaQueryData(textScaleFactor: 3.0),
|
||||
child: Center(
|
||||
child: TextButton(
|
||||
onPressed: () { },
|
||||
child: const Text('ABC'),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -581,7 +608,6 @@ void main() {
|
||||
expect(tester.getSize(find.byType(Text)).height, equals(42.0));
|
||||
});
|
||||
|
||||
|
||||
testWidgets('TextButton size is configurable by ThemeData.materialTapTargetSize', (WidgetTester tester) async {
|
||||
Widget buildFrame(MaterialTapTargetSize tapTargetSize, Key key) {
|
||||
return Theme(
|
||||
@ -591,6 +617,7 @@ void main() {
|
||||
child: Center(
|
||||
child: TextButton(
|
||||
key: key,
|
||||
style: TextButton.styleFrom(minimumSize: const Size(64, 36)),
|
||||
child: const SizedBox(width: 50.0, height: 8.0),
|
||||
onPressed: () { },
|
||||
),
|
||||
@ -855,6 +882,7 @@ void main() {
|
||||
Future<void> buildTest(VisualDensity visualDensity, { bool useText = false }) async {
|
||||
return tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(textTheme: Typography.englishLike2014),
|
||||
home: Directionality(
|
||||
textDirection: TextDirection.rtl,
|
||||
child: Center(
|
||||
@ -993,7 +1021,15 @@ void main() {
|
||||
testWidgets(testName, (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData.from(colorScheme: const ColorScheme.light()),
|
||||
theme: ThemeData(
|
||||
colorScheme: const ColorScheme.light(),
|
||||
// Force Material 2 defaults for the typography and size
|
||||
// default values as the test was designed against these settings.
|
||||
textTheme: Typography.englishLike2014,
|
||||
textButtonTheme: TextButtonThemeData(
|
||||
style: TextButton.styleFrom(minimumSize: const Size(64, 36)),
|
||||
),
|
||||
),
|
||||
home: Builder(
|
||||
builder: (BuildContext context) {
|
||||
return MediaQuery(
|
||||
@ -1227,8 +1263,8 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
// Default splashFactory (from Theme.of().splashFactory), one splash circle drawn.
|
||||
await tester.pumpWidget(buildFrame());
|
||||
// InkRipple.splashFactory, one splash circle drawn.
|
||||
await tester.pumpWidget(buildFrame(splashFactory: InkRipple.splashFactory));
|
||||
{
|
||||
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
||||
final MaterialInkController material = Material.of(tester.element(find.text('test')))!;
|
||||
@ -1352,6 +1388,7 @@ void main() {
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(textTheme: Typography.englishLike2014),
|
||||
home: Scaffold(
|
||||
body: Center(
|
||||
child: Column(
|
||||
|
Loading…
x
Reference in New Issue
Block a user