Unverified Commit eea3465a authored by Hans Muller's avatar Hans Muller Committed by GitHub

Added ColorScheme, updated ThemeData, ButtonTheme, material buttons (#22013)

Introduce an overall material "color scheme" and to make it possible to redefine how a component's visual properties bind to the color scheme and to the existing material Theme.
parent 46bc911b
...@@ -25,6 +25,9 @@ TextTheme _buildTextTheme(TextTheme base) { ...@@ -25,6 +25,9 @@ TextTheme _buildTextTheme(TextTheme base) {
ThemeData _buildDarkTheme() { ThemeData _buildDarkTheme() {
const Color primaryColor = Color(0xFF0175c2); const Color primaryColor = Color(0xFF0175c2);
final ThemeData base = ThemeData.dark(); final ThemeData base = ThemeData.dark();
final ColorScheme colorScheme = const ColorScheme.dark().copyWith(
primary: primaryColor,
);
return base.copyWith( return base.copyWith(
primaryColor: primaryColor, primaryColor: primaryColor,
buttonColor: primaryColor, buttonColor: primaryColor,
...@@ -34,7 +37,8 @@ ThemeData _buildDarkTheme() { ...@@ -34,7 +37,8 @@ ThemeData _buildDarkTheme() {
scaffoldBackgroundColor: const Color(0xFF202124), scaffoldBackgroundColor: const Color(0xFF202124),
backgroundColor: const Color(0xFF202124), backgroundColor: const Color(0xFF202124),
errorColor: const Color(0xFFB00020), errorColor: const Color(0xFFB00020),
buttonTheme: const ButtonThemeData( buttonTheme: ButtonThemeData(
colorScheme: colorScheme,
textTheme: ButtonTextTheme.primary, textTheme: ButtonTextTheme.primary,
), ),
textTheme: _buildTextTheme(base.textTheme), textTheme: _buildTextTheme(base.textTheme),
...@@ -45,8 +49,12 @@ ThemeData _buildDarkTheme() { ...@@ -45,8 +49,12 @@ ThemeData _buildDarkTheme() {
ThemeData _buildLightTheme() { ThemeData _buildLightTheme() {
const Color primaryColor = Color(0xFF0175c2); const Color primaryColor = Color(0xFF0175c2);
final ColorScheme colorScheme = const ColorScheme.light().copyWith(
primary: primaryColor,
);
final ThemeData base = ThemeData.light(); final ThemeData base = ThemeData.light();
return base.copyWith( return base.copyWith(
colorScheme: colorScheme,
primaryColor: primaryColor, primaryColor: primaryColor,
buttonColor: primaryColor, buttonColor: primaryColor,
indicatorColor: Colors.white, indicatorColor: Colors.white,
...@@ -57,7 +65,8 @@ ThemeData _buildLightTheme() { ...@@ -57,7 +65,8 @@ ThemeData _buildLightTheme() {
scaffoldBackgroundColor: Colors.white, scaffoldBackgroundColor: Colors.white,
backgroundColor: Colors.white, backgroundColor: Colors.white,
errorColor: const Color(0xFFB00020), errorColor: const Color(0xFFB00020),
buttonTheme: const ButtonThemeData( buttonTheme: ButtonThemeData(
colorScheme: colorScheme,
textTheme: ButtonTextTheme.primary, textTheme: ButtonTextTheme.primary,
), ),
textTheme: _buildTextTheme(base.textTheme), textTheme: _buildTextTheme(base.textTheme),
......
...@@ -380,12 +380,12 @@ void main() { ...@@ -380,12 +380,12 @@ void main() {
handle.dispose(); handle.dispose();
}); });
testWidgets('overscroll_demo $themeName', (WidgetTester tester) async { testWidgets('overscroll_demo', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics(); final SemanticsHandle handle = tester.ensureSemantics();
await tester.pumpWidget(MaterialApp(theme: theme, home: const OverscrollDemo())); await tester.pumpWidget(const MaterialApp(home: OverscrollDemo()));
await expectLater(tester, meetsGuideline(textContrastGuideline)); await expectLater(tester, meetsGuideline(textContrastGuideline));
handle.dispose(); handle.dispose();
}); });
testWidgets('page_selector_demo $themeName', (WidgetTester tester) async { testWidgets('page_selector_demo $themeName', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics(); final SemanticsHandle handle = tester.ensureSemantics();
......
...@@ -32,6 +32,7 @@ export 'src/material/checkbox_list_tile.dart'; ...@@ -32,6 +32,7 @@ export 'src/material/checkbox_list_tile.dart';
export 'src/material/chip.dart'; export 'src/material/chip.dart';
export 'src/material/chip_theme.dart'; export 'src/material/chip_theme.dart';
export 'src/material/circle_avatar.dart'; export 'src/material/circle_avatar.dart';
export 'src/material/color_scheme.dart';
export 'src/material/colors.dart'; export 'src/material/colors.dart';
export 'src/material/constants.dart'; export 'src/material/constants.dart';
export 'src/material/data_table.dart'; export 'src/material/data_table.dart';
...@@ -65,6 +66,7 @@ export 'src/material/input_border.dart'; ...@@ -65,6 +66,7 @@ export 'src/material/input_border.dart';
export 'src/material/input_decorator.dart'; export 'src/material/input_decorator.dart';
export 'src/material/list_tile.dart'; export 'src/material/list_tile.dart';
export 'src/material/material.dart'; export 'src/material/material.dart';
export 'src/material/material_button.dart';
export 'src/material/material_localizations.dart'; export 'src/material/material_localizations.dart';
export 'src/material/mergeable_material.dart'; export 'src/material/mergeable_material.dart';
export 'src/material/outline_button.dart'; export 'src/material/outline_button.dart';
......
...@@ -9,7 +9,6 @@ import 'package:flutter/rendering.dart'; ...@@ -9,7 +9,6 @@ import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'button_theme.dart'; import 'button_theme.dart';
import 'colors.dart';
import 'constants.dart'; import 'constants.dart';
import 'ink_well.dart'; import 'ink_well.dart';
import 'material.dart'; import 'material.dart';
...@@ -225,238 +224,6 @@ class _RawMaterialButtonState extends State<RawMaterialButton> { ...@@ -225,238 +224,6 @@ class _RawMaterialButtonState extends State<RawMaterialButton> {
} }
} }
/// A utility class for building Material buttons that depend on the
/// ambient [ButtonTheme] and [Theme].
///
/// The button's size will expand to fit the child widget, if necessary.
///
/// MaterialButtons whose [onPressed] handler is null will be disabled. To have
/// an enabled button, make sure to pass a non-null value for onPressed.
///
/// Rather than using this class directly, consider using [FlatButton] or
/// [RaisedButton], which configure this class with appropriate defaults that
/// match the material design specification.
///
/// To create a button directly, without inheriting theme defaults, use
/// [RawMaterialButton].
///
/// If you want an ink-splash effect for taps, but don't want to use a button,
/// consider using [InkWell] directly.
///
/// See also:
///
/// * [IconButton], to create buttons that contain icons rather than text.
class MaterialButton extends StatelessWidget {
/// Creates a material button.
///
/// Rather than creating a material button directly, consider using
/// [FlatButton] or [RaisedButton]. To create a custom Material button
/// consider using [RawMaterialButton].
///
/// The [clipBehavior] argument must not be null.
const MaterialButton({
Key key,
this.colorBrightness,
this.textTheme,
this.textColor,
this.color,
this.highlightColor,
this.splashColor,
this.elevation,
this.highlightElevation,
this.minWidth,
this.height,
this.padding,
this.materialTapTargetSize,
this.clipBehavior = Clip.none,
@required this.onPressed,
this.child
}) : assert(clipBehavior != null), super(key: key);
/// The theme brightness to use for this button.
///
/// Defaults to the brightness from [ThemeData.brightness].
final Brightness colorBrightness;
/// Defines the button's base colors, and the defaults for the button's minimum
/// size, internal padding, and shape.
final ButtonTextTheme textTheme;
/// The color to use for this button's text.
final Color textColor;
/// The button's fill color, displayed by its [Material], while the button
/// is in its default (unpressed, enabled) state.
///
/// Defaults to null, meaning that the color is automatically derived from the [Theme].
///
/// Typically, a material design color will be used, as follows:
///
/// ```dart
/// MaterialButton(
/// color: Colors.blue[500],
/// onPressed: _handleTap,
/// child: Text('DEMO'),
/// ),
/// ```
final Color color;
/// The primary color of the button when the button is in the down (pressed)
/// state.
///
/// The splash is represented as a circular overlay that appears above the
/// [highlightColor] overlay. The splash overlay has a center point that
/// matches the hit point of the user touch event. The splash overlay will
/// expand to 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.
///
/// Defaults to the Theme's splash color, [ThemeData.splashColor].
final Color splashColor;
/// The secondary color of the button when the button is in the down (pressed)
/// state.
///
/// The highlight color is represented as a solid color that is overlaid over
/// the button color (if any). If the highlight color has transparency, the
/// button color will show through. The highlight fades in quickly as the
/// button is held down.
///
/// Defaults to the Theme's highlight color, [ThemeData.highlightColor].
final Color highlightColor;
/// The z-coordinate at which to place this button. This controls the size of
/// the shadow below the button.
///
/// Defaults to 0.
///
/// See also:
///
/// * [FlatButton], a material button specialized for the case where the
/// elevation is zero.
/// * [RaisedButton], a material button specialized for the case where the
/// elevation is non-zero.
final double elevation;
/// The z-coordinate at which to place this button when highlighted. This
/// controls the size of the shadow below the button.
///
/// Defaults to 0.
///
/// See also:
///
/// * [elevation], the default elevation.
final double highlightElevation;
/// The smallest horizontal extent that the button will occupy.
///
/// Defaults to the value from the current [ButtonTheme].
final double minWidth;
/// The vertical extent of the button.
///
/// Defaults to the value from the current [ButtonTheme].
final double height;
/// The internal padding for the button's [child].
///
/// Defaults to the value from the current [ButtonTheme],
/// [ButtonThemeData.padding].
final EdgeInsetsGeometry padding;
/// The callback that is called when the button is tapped or otherwise activated.
///
/// If this is set to null, the button will be disabled.
final VoidCallback onPressed;
/// The widget below this widget in the tree.
///
/// {@macro flutter.widgets.child}
final Widget child;
/// Configures the minimum size of the tap target.
///
/// Defaults to [ThemeData.materialTapTargetSize].
///
/// See also:
///
/// * [MaterialTapTargetSize], for a description of how this affects tap targets.
final MaterialTapTargetSize materialTapTargetSize;
/// {@macro flutter.widgets.Clip}
final Clip clipBehavior;
/// Whether the button is enabled or disabled. Buttons are disabled by default. To
/// enable a button, set its [onPressed] property to a non-null value.
bool get enabled => onPressed != null;
Brightness _getBrightness(ThemeData theme) {
return colorBrightness ?? theme.brightness;
}
ButtonTextTheme _getTextTheme(ButtonThemeData buttonTheme) {
return textTheme ?? buttonTheme.textTheme;
}
Color _getTextColor(ThemeData theme, ButtonThemeData buttonTheme, Color fillColor) {
if (textColor != null)
return textColor;
final bool themeIsDark = _getBrightness(theme) == Brightness.dark;
final bool fillIsDark = fillColor != null
? ThemeData.estimateBrightnessForColor(fillColor) == Brightness.dark
: themeIsDark;
switch (_getTextTheme(buttonTheme)) {
case ButtonTextTheme.normal:
return enabled
? (themeIsDark ? Colors.white : Colors.black87)
: theme.disabledColor;
case ButtonTextTheme.accent:
return enabled
? theme.accentColor
: theme.disabledColor;
case ButtonTextTheme.primary:
return enabled
? (fillIsDark ? Colors.white : Colors.black)
: (themeIsDark ? Colors.white30 : Colors.black38);
}
return null;
}
@override
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
final ButtonThemeData buttonTheme = ButtonTheme.of(context);
final Color textColor = _getTextColor(theme, buttonTheme, color);
return RawMaterialButton(
onPressed: onPressed,
fillColor: color,
textStyle: theme.textTheme.button.copyWith(color: textColor),
highlightColor: highlightColor ?? theme.highlightColor,
splashColor: splashColor ?? theme.splashColor,
elevation: elevation ?? 2.0,
highlightElevation: highlightElevation ?? 8.0,
padding: padding ?? buttonTheme.padding,
constraints: buttonTheme.constraints.copyWith(
minWidth: minWidth,
minHeight: height,
),
shape: buttonTheme.shape,
child: child,
materialTapTargetSize: materialTapTargetSize ?? theme.materialTapTargetSize,
clipBehavior: clipBehavior,
);
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(FlagProperty('enabled', value: enabled, ifFalse: 'disabled'));
}
}
/// A widget to pad the area around a [MaterialButton]'s inner [Material]. /// A widget to pad the area around a [MaterialButton]'s inner [Material].
/// ///
/// Redirect taps that occur in the padded area around the child to the center /// Redirect taps that occur in the padded area around the child to the center
......
This diff is collapsed.
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'button.dart';
import 'button_theme.dart';
import 'constants.dart';
import 'ink_well.dart';
import 'material.dart';
import 'theme.dart';
import 'theme_data.dart';
/// A utility class for building Material buttons that depend on the
/// ambient [ButtonTheme] and [Theme].
///
/// The button's size will expand to fit the child widget, if necessary.
///
/// MaterialButtons whose [onPressed] handler is null will be disabled. To have
/// an enabled button, make sure to pass a non-null value for onPressed.
///
/// Rather than using this class directly, consider using [FlatButton],
/// OutlineButton, or [RaisedButton], which configure this class with
/// appropriate defaults that match the material design specification.
///
/// To create a button directly, without inheriting theme defaults, use
/// [RawMaterialButton].
///
/// If you want an ink-splash effect for taps, but don't want to use a button,
/// consider using [InkWell] directly.
///
/// See also:
///
/// * [IconButton], to create buttons that contain icons rather than text.
class MaterialButton extends StatelessWidget {
/// Creates a material button.
///
/// Rather than creating a material button directly, consider using
/// [FlatButton] or [RaisedButton]. To create a custom Material button
/// consider using [RawMaterialButton].
///
/// The [clipBehavior] argument must not be null.
const MaterialButton({
Key key,
@required this.onPressed,
this.onHighlightChanged,
this.textTheme,
this.textColor,
this.disabledTextColor,
this.color,
this.disabledColor,
this.highlightColor,
this.splashColor,
this.colorBrightness,
this.elevation,
this.highlightElevation,
this.disabledElevation,
this.padding,
this.shape,
this.clipBehavior = Clip.none,
this.materialTapTargetSize,
this.animationDuration,
this.minWidth,
this.height,
this.child,
}) : super(key: key);
/// The callback that is called when the button is tapped or otherwise activated.
///
/// If this is set to null, the button will be disabled.
final VoidCallback onPressed;
/// Called by the underlying [InkWell] widget's [InkWell.onHighlightChanged]
/// callback.
final ValueChanged<bool> onHighlightChanged;
/// Defines the button's base colors, and the defaults for the button's minimum
/// size, internal padding, and shape.
///
/// Defaults to `ButtonTheme.of(context).textTheme`.
final ButtonTextTheme textTheme;
/// The color to use for this button's text.
///
/// The button's [Material.textStyle] will be the current theme's button
/// text style, [ThemeData.textTheme.button], configured with this color.
///
/// The default text color depends on the button theme's text theme,
/// [ButtonThemeData.textTheme].
///
/// See also:
/// * [disabledTextColor], the text color to use when the button has been
/// disabled.
final Color textColor;
/// The color to use for this button's text when the button is disabled.
///
/// The button's [Material.textStyle] will be the current theme's button
/// text style, [ThemeData.textTheme.button], configured with this color.
///
/// The default value is the theme's disabled color,
/// [ThemeData.disabledColor].
///
/// See also:
/// * [textColor] - The color to use for this button's text when the button is [enabled].
final Color disabledTextColor;
/// The button's fill color, displayed by its [Material], while it
/// is in its default (unpressed, [enabled]) state.
///
/// The default fill color is the theme's button color, [ThemeData.buttonColor].
///
/// See also:
/// * [disabledColor] - the fill color of the button when the button is disabled.
final Color color;
/// The fill color of the button when the button is disabled.
///
/// The default value of this color is the theme's disabled color,
/// [ThemeData.disabledColor].
///
/// See also:
/// * [color] - the fill color of the button when the button is [enabled].
final Color disabledColor;
/// The splash color of the button's [InkWell].
///
/// The ink splash indicates that the button has been touched. It
/// appears on top of the button's child and spreads in an expanding
/// circle beginning where the touch occurred.
///
/// The default splash color is the current theme's splash color,
/// [ThemeData.splashColor].
///
/// The appearance of the splash can be configured with the theme's splash
/// factory, [ThemeData.splashFactory].
final Color splashColor;
/// The highlight color of the button's [InkWell].
///
/// The highlight indicates that the button is actively being pressed. It
/// appears on top of the button's child and quickly spreads to fill
/// the button, and then fades out.
///
/// If [textTheme] is [ButtonTextTheme.primary], the default highlight color is
/// transparent (in other words the highlight doesn't appear). Otherwise it's
/// the current theme's highlight color, [ThemeData.highlightColor].
final Color highlightColor;
/// The z-coordinate at which to place this button. This controls the size of
/// the shadow below the raised button.
///
/// Defaults to 2, the appropriate elevation for raised buttons.
///
/// See also:
///
/// * [FlatButton], a button with no elevation or fill color.
/// * [disabledElevation], the elevation when the button is disabled.
/// * [highlightElevation], the elevation when the button is pressed.
final double elevation;
/// The elevation for the button's [Material] when the button
/// is [enabled] and pressed.
///
/// This controls the size of the shadow below the button. When a tap
/// down gesture occurs within the button, its [InkWell] displays a
/// [highlightColor] "highlight".
///
/// Defaults to 8.0.
///
/// See also:
///
/// * [elevation], the default elevation.
/// * [disabledElevation], the elevation when the button is disabled.
final double highlightElevation;
/// The elevation for the button's [Material] when the button
/// is not [enabled].
///
/// Defaults to 0.0.
///
/// See also:
///
/// * [elevation], the default elevation.
/// * [highlightElevation], the elevation when the button is pressed.
final double disabledElevation;
/// The theme brightness to use for this button.
///
/// Defaults to the theme's brightness, [ThemeData.brightness].
final Brightness colorBrightness;
/// The button's label.
///
/// Often a [Text] widget in all caps.
final Widget child;
/// Whether the button is enabled or disabled.
///
/// Buttons are disabled by default. To enable a button, set its [onPressed]
/// property to a non-null value.
bool get enabled => onPressed != null;
/// The internal padding for the button's [child].
///
/// Defaults to the value from the current [ButtonTheme],
/// [ButtonThemeData.padding].
final EdgeInsetsGeometry padding;
/// The shape of the button's [Material].
///
/// The button's highlight and splash are clipped to this shape. If the
/// button has an elevation, then its drop shadow is defined by this
/// shape as well.
final ShapeBorder shape;
/// {@macro flutter.widgets.Clip}
final Clip clipBehavior;
/// Defines the duration of animated changes for [shape] and [elevation].
///
/// The default value is [kThemeChangeDuration].
final Duration animationDuration;
/// Configures the minimum size of the tap target.
///
/// Defaults to [ThemeData.materialTapTargetSize].
///
/// See also:
///
/// * [MaterialTapTargetSize], for a description of how this affects tap targets.
final MaterialTapTargetSize materialTapTargetSize;
/// The smallest horizontal extent that the button will occupy.
///
/// Defaults to the value from the current [ButtonTheme].
final double minWidth;
/// The vertical extent of the button.
///
/// Defaults to the value from the current [ButtonTheme].
final double height;
@override
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
final ButtonThemeData buttonTheme = ButtonTheme.of(context);
return RawMaterialButton(
onPressed: onPressed,
fillColor: color,
textStyle: theme.textTheme.button.copyWith(color: buttonTheme.getTextColor(this)),
highlightColor: highlightColor ?? theme.highlightColor,
splashColor: splashColor ?? theme.splashColor,
elevation: buttonTheme.getElevation(this),
highlightElevation: buttonTheme.getHighlightElevation(this),
padding: buttonTheme.getPadding(this),
constraints: buttonTheme.constraints,
shape: buttonTheme.shape,
clipBehavior: clipBehavior ?? Clip.none,
animationDuration: buttonTheme.getAnimationDuration(this),
child: child,
materialTapTargetSize: materialTapTargetSize ?? theme.materialTapTargetSize,
);
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(FlagProperty('enabled', value: enabled, ifFalse: 'disabled'));
}
}
/// The type of [MaterialButton]s created with [RaisedButton.icon], [FlatButton.icon],
/// and [OutlineButton.icon].
///
/// This mixin only exists to give the "label and icon" button widgets a distinct
/// type for the sake of [ButtonTheme].
mixin MaterialButtonWithIconMixin { }
...@@ -107,10 +107,12 @@ void main() { ...@@ -107,10 +107,12 @@ void main() {
EdgeInsets padding; EdgeInsets padding;
ShapeBorder shape; ShapeBorder shape;
const Color disabledColor = Color(0xFF00FF00);
await tester.pumpWidget( await tester.pumpWidget(
Theme( Theme(
data: lightTheme.copyWith( data: lightTheme.copyWith(
disabledColor: const Color(0xFF00FF00), // disabled RaisedButton fill color disabledColor: disabledColor, // disabled RaisedButton fill color
buttonTheme: const ButtonThemeData(disabledColor: disabledColor),
textTheme: lightTheme.textTheme.copyWith( textTheme: lightTheme.textTheme.copyWith(
button: lightTheme.textTheme.button.copyWith( button: lightTheme.textTheme.button.copyWith(
// The button's height will match because there's no // The button's height will match because there's no
...@@ -149,7 +151,7 @@ void main() { ...@@ -149,7 +151,7 @@ void main() {
)); ));
expect(tester.widget<Material>(find.byType(Material)).shape, shape); expect(tester.widget<Material>(find.byType(Material)).shape, shape);
expect(tester.widget<Material>(find.byType(Material)).color, const Color(0xFF00FF00)); expect(tester.widget<Material>(find.byType(Material)).color, disabledColor);
expect(tester.getSize(find.byType(Material)), const Size(88.0, 48.0)); expect(tester.getSize(find.byType(Material)), const Size(88.0, 48.0));
}); });
...@@ -169,6 +171,7 @@ void main() { ...@@ -169,6 +171,7 @@ void main() {
minWidth: 100.0, minWidth: 100.0,
height: 200.0, height: 200.0,
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
buttonColor: const Color(0xFF00FF00), // enabled RaisedButton fill color
shape: const RoundedRectangleBorder(), shape: const RoundedRectangleBorder(),
child: Builder( child: Builder(
builder: (BuildContext context) { builder: (BuildContext context) {
......
...@@ -89,7 +89,7 @@ void main() { ...@@ -89,7 +89,7 @@ void main() {
// Expect that the button is disabled and painted with the disabled border color. // Expect that the button is disabled and painted with the disabled border color.
expect(tester.widget<OutlineButton>(outlineButton).enabled, false); expect(tester.widget<OutlineButton>(outlineButton).enabled, false);
expect( expect(
outlineButton, outlineButton, //find.byType(OutlineButton),
paints paints
..clipPath(pathMatcher: coversSameAreaAs(clipPath, areaToCompare: clipRect.inflate(10.0))) ..clipPath(pathMatcher: coversSameAreaAs(clipPath, areaToCompare: clipRect.inflate(10.0)))
..path(color: disabledBorderColor, strokeWidth: borderWidth)); ..path(color: disabledBorderColor, strokeWidth: borderWidth));
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
const ShapeBorder defaultButtonShape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(2.0)));
const EdgeInsets defaultButtonPadding = EdgeInsets.only(left: 16.0, right: 16.0);
const BoxConstraints defaultButtonConstraints = BoxConstraints(minWidth: 88.0, minHeight: 36.0);
const Duration defaultButtonDuration = Duration(milliseconds: 200);
void main() {
group('RaisedButton', () {
testWidgets('theme: ThemeData.light(), enabled: true', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
theme: ThemeData.light(),
home: Center(
child: RaisedButton(
onPressed: () { }, // button.enabled == true
child: const Text('button'),
)
),
),
);
final RawMaterialButton raw = tester.widget<RawMaterialButton>(find.byType(RawMaterialButton));
expect(raw.textStyle.color, const Color(0xdd000000));
expect(raw.fillColor, const Color(0xffe0e0e0));
expect(raw.highlightColor, const Color(0x29000000)); // Was Color(0x66bcbcbc)
expect(raw.splashColor, const Color(0x1f000000)); // Was Color(0x66c8c8c8)
expect(raw.elevation, 2.0);
expect(raw.highlightElevation, 8.0);
expect(raw.disabledElevation, 0.0);
expect(raw.constraints, defaultButtonConstraints);
expect(raw.padding, defaultButtonPadding);
expect(raw.shape, defaultButtonShape);
expect(raw.animationDuration, defaultButtonDuration);
expect(raw.materialTapTargetSize, MaterialTapTargetSize.padded);
});
testWidgets('theme: ThemeData.light(), enabled: false', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
theme: ThemeData.light(),
home: const Center(
child: RaisedButton(
onPressed: null, // button.enabled == false
child: Text('button'),
)
),
),
);
final RawMaterialButton raw = tester.widget<RawMaterialButton>(find.byType(RawMaterialButton));
expect(raw.textStyle.color, const Color(0x61000000));
expect(raw.fillColor, const Color(0x61000000));
// highlightColor, disabled button can't be pressed
// splashColor, disabled button doesn't splash
expect(raw.elevation, 2.0);
expect(raw.highlightElevation, 8.0);
expect(raw.disabledElevation, 0.0);
expect(raw.constraints, defaultButtonConstraints);
expect(raw.padding, defaultButtonPadding);
expect(raw.shape, defaultButtonShape);
expect(raw.animationDuration, defaultButtonDuration);
expect(raw.materialTapTargetSize, MaterialTapTargetSize.padded);
});
});
group('FlatButton', () {
testWidgets('theme: ThemeData.light(), enabled: true', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
theme: ThemeData.light(),
home: Center(
child: FlatButton(
onPressed: () { }, // button.enabled == true
child: const Text('button'),
)
),
),
);
final RawMaterialButton raw = tester.widget<RawMaterialButton>(find.byType(RawMaterialButton));
expect(raw.textStyle.color, const Color(0xdd000000));
expect(raw.fillColor, null);
expect(raw.highlightColor, const Color(0x29000000)); // Was Color(0x66bcbcbc)
expect(raw.splashColor, const Color(0x1f000000)); // Was Color(0x66c8c8c8)
expect(raw.elevation, 0.0);
expect(raw.highlightElevation, 0.0);
expect(raw.disabledElevation, 0.0);
expect(raw.constraints, defaultButtonConstraints);
expect(raw.padding, defaultButtonPadding);
expect(raw.shape, defaultButtonShape);
expect(raw.animationDuration, defaultButtonDuration);
expect(raw.materialTapTargetSize, MaterialTapTargetSize.padded);
});
testWidgets('theme: ThemeData.light(), enabled: false', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
theme: ThemeData.light(),
home: const Center(
child: FlatButton(
onPressed: null, // button.enabled == false
child: Text('button'),
)
),
),
);
final RawMaterialButton raw = tester.widget<RawMaterialButton>(find.byType(RawMaterialButton));
expect(raw.textStyle.color, const Color(0x61000000));
expect(raw.fillColor, null);
// highlightColor, disabled button can't be pressed
// splashColor, disabled button doesn't splash
expect(raw.elevation, 0.0);
expect(raw.highlightElevation, 0.0);
expect(raw.disabledElevation, 0.0);
expect(raw.constraints, defaultButtonConstraints);
expect(raw.padding, defaultButtonPadding);
expect(raw.shape, defaultButtonShape);
expect(raw.animationDuration, const Duration(milliseconds: 200));
expect(raw.materialTapTargetSize, MaterialTapTargetSize.padded);
});
});
group('OutlineButton', () {
testWidgets('theme: ThemeData.light(), enabled: true', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
theme: ThemeData.light(),
home: Center(
child: OutlineButton(
onPressed: () { }, // button.enabled == true
child: const Text('button'),
)
),
),
);
final RawMaterialButton raw = tester.widget<RawMaterialButton>(find.byType(RawMaterialButton));
expect(raw.textStyle.color, const Color(0xdd000000));
expect(raw.fillColor, const Color(0x00ffffff));
expect(raw.highlightColor, const Color(0x29000000)); // Was Color(0x66bcbcbc)
expect(raw.splashColor, const Color(0x1f000000)); // Was Color(0x66c8c8c8)
expect(raw.elevation, 0.0);
expect(raw.highlightElevation, 0.0);
expect(raw.disabledElevation, 0.0);
expect(raw.constraints, defaultButtonConstraints);
expect(raw.padding, defaultButtonPadding);
// animationDuration can't be configed by the theme/constructor
expect(raw.materialTapTargetSize, MaterialTapTargetSize.padded);
});
testWidgets('theme: ThemeData.light(), enabled: false', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
theme: ThemeData.light(),
home: const Center(
child: OutlineButton(
onPressed: null, // button.enabled == false
child: Text('button'),
)
),
),
);
final RawMaterialButton raw = tester.widget<RawMaterialButton>(find.byType(RawMaterialButton));
expect(raw.textStyle.color, const Color(0x61000000));
expect(raw.fillColor, const Color(0x00000000));
// highlightColor, disabled button can't be pressed
// splashColor, disabled button doesn't splash
expect(raw.elevation, 0.0);
expect(raw.highlightElevation, 0.0);
expect(raw.disabledElevation, 0.0);
expect(raw.constraints, defaultButtonConstraints);
expect(raw.padding, defaultButtonPadding);
// animationDuration can't be configed by the theme/constructor
expect(raw.materialTapTargetSize, MaterialTapTargetSize.padded);
});
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment