Unverified Commit bdf582fd authored by Anthony's avatar Anthony Committed by GitHub

[Material] Create a FloatingActionButton ThemeData and honor it within the...

[Material] Create a FloatingActionButton ThemeData and honor it within the FloatingActionButton (#28735)

Adds a FloatingActionButtonThemeData so that FABs can be themed at the Theme level and independently. The properties that are now on the theme must be defaulted at the build level, in order to respect any contributing theme properties. Because of this, some tests had to be modified to look at properties after they are built. Also, since default behaviors are now tested in the FAB Theme test, some default tests in the FAB test no longer applied and were removed.

The themable properties are:
-backgroundColor
-foregroundColor
-elevation
-disabledElevation
-highlightElevation
-shape
parent 5f727126
......@@ -56,6 +56,7 @@ export 'src/material/flat_button.dart';
export 'src/material/flexible_space_bar.dart';
export 'src/material/floating_action_button.dart';
export 'src/material/floating_action_button_location.dart';
export 'src/material/floating_action_button_theme.dart';
export 'src/material/flutter_logo.dart';
export 'src/material/grid_tile.dart';
export 'src/material/grid_tile_bar.dart';
......
......@@ -9,6 +9,7 @@ import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'button.dart';
import 'floating_action_button_theme.dart';
import 'scaffold.dart';
import 'theme.dart';
import 'theme_data.dart';
......@@ -114,10 +115,9 @@ class _DefaultHeroTag {
class FloatingActionButton extends StatelessWidget {
/// Creates a circular floating action button.
///
/// The [elevation], [highlightElevation], [mini], [shape], and [clipBehavior]
/// arguments must not be null. Additionally, [elevation],
/// [highlightElevation], and [disabledElevation] (if specified) must be
/// non-negative.
/// The [mini] and [clipBehavior] arguments must be non-null. Additionally,
/// [elevation], [highlightElevation], and [disabledElevation] (if specified)
/// must be non-negative.
const FloatingActionButton({
Key key,
this.child,
......@@ -125,56 +125,51 @@ class FloatingActionButton extends StatelessWidget {
this.foregroundColor,
this.backgroundColor,
this.heroTag = const _DefaultHeroTag(),
this.elevation = 6.0,
this.highlightElevation = 12.0,
double disabledElevation,
this.elevation,
this.highlightElevation,
this.disabledElevation,
@required this.onPressed,
this.mini = false,
this.shape = const CircleBorder(),
this.shape,
this.clipBehavior = Clip.none,
this.materialTapTargetSize,
this.isExtended = false,
}) : assert(elevation != null && elevation >= 0.0),
assert(highlightElevation != null && highlightElevation >= 0.0),
}) : assert(elevation == null || elevation >= 0.0),
assert(highlightElevation == null || highlightElevation >= 0.0),
assert(disabledElevation == null || disabledElevation >= 0.0),
assert(mini != null),
assert(shape != null),
assert(isExtended != null),
_sizeConstraints = mini ? _kMiniSizeConstraints : _kSizeConstraints,
disabledElevation = disabledElevation ?? elevation,
super(key: key);
/// Creates a wider [StadiumBorder]-shaped floating action button with
/// an optional [icon] and a [label].
///
/// The [label], [elevation], [highlightElevation], [clipBehavior] and
/// [shape] arguments must not be null. Additionally, [elevation]
/// [highlightElevation], and [disabledElevation] (if specified) must be
/// non-negative.
/// The [label] and [clipBehavior] arguments must non-null. Additionally,
/// [elevation], [highlightElevation], and [disabledElevation] (if specified)
/// must be non-negative.
FloatingActionButton.extended({
Key key,
this.tooltip,
this.foregroundColor,
this.backgroundColor,
this.heroTag = const _DefaultHeroTag(),
this.elevation = 6.0,
this.highlightElevation = 12.0,
double disabledElevation,
this.elevation,
this.highlightElevation,
this.disabledElevation,
@required this.onPressed,
this.shape = const StadiumBorder(),
this.shape,
this.isExtended = true,
this.materialTapTargetSize,
this.clipBehavior = Clip.none,
Widget icon,
@required Widget label,
}) : assert(elevation != null && elevation >= 0.0),
assert(highlightElevation != null && highlightElevation >= 0.0),
}) : assert(elevation == null || elevation >= 0.0),
assert(highlightElevation == null || highlightElevation >= 0.0),
assert(disabledElevation == null || disabledElevation >= 0.0),
assert(shape != null),
assert(isExtended != null),
assert(clipBehavior != null),
_sizeConstraints = _kExtendedSizeConstraints,
disabledElevation = disabledElevation ?? elevation,
mini = false,
child = _ChildOverflowBox(
child: Row(
......@@ -319,10 +314,42 @@ class FloatingActionButton extends StatelessWidget {
final BoxConstraints _sizeConstraints;
static const double _defaultElevation = 6;
static const double _defaultHighlightElevation = 12;
static const ShapeBorder _defaultShape = CircleBorder();
static const ShapeBorder _defaultExtendedShape = StadiumBorder();
@override
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
final Color foregroundColor = this.foregroundColor ?? theme.accentIconTheme.color;
final FloatingActionButtonThemeData floatingActionButtonTheme = theme.floatingActionButtonTheme;
final Color backgroundColor = this.backgroundColor
?? floatingActionButtonTheme.backgroundColor
?? theme.colorScheme.secondary;
final Color foregroundColor = this.foregroundColor
?? floatingActionButtonTheme.foregroundColor
?? theme.accentIconTheme.color
?? theme.colorScheme.onSecondary;
final double elevation = this.elevation
?? floatingActionButtonTheme.elevation
?? _defaultElevation;
final double disabledElevation = this.disabledElevation
?? floatingActionButtonTheme.disabledElevation
?? elevation;
final double highlightElevation = this.highlightElevation
?? floatingActionButtonTheme.highlightElevation
?? _defaultHighlightElevation;
final MaterialTapTargetSize materialTapTargetSize = this.materialTapTargetSize
?? theme.materialTapTargetSize;
final TextStyle textStyle = theme.accentTextTheme.button.copyWith(
color: foregroundColor,
letterSpacing: 1.2,
);
final ShapeBorder shape = this.shape
?? floatingActionButtonTheme.shape
?? (isExtended ? _defaultExtendedShape : _defaultShape);
Widget result;
if (child != null) {
......@@ -340,12 +367,9 @@ class FloatingActionButton extends StatelessWidget {
highlightElevation: highlightElevation,
disabledElevation: disabledElevation,
constraints: _sizeConstraints,
materialTapTargetSize: materialTapTargetSize ?? theme.materialTapTargetSize,
fillColor: backgroundColor ?? theme.accentColor,
textStyle: theme.accentTextTheme.button.copyWith(
color: foregroundColor,
letterSpacing: 1.2,
),
materialTapTargetSize: materialTapTargetSize,
fillColor: backgroundColor,
textStyle: textStyle,
shape: shape,
clipBehavior: clipBehavior,
child: result,
......
// Copyright 2019 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 'dart:ui' show lerpDouble;
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
/// Defines default property values for descendant [FloatingActionButton]
/// widgets.
///
/// Descendant widgets obtain the current [FloatingActionButtonThemeData] object
/// using `Theme.of(context).floatingActionButtonTheme`. Instances of
/// [FloatingActionButtonThemeData] can be customized with
/// [FloatingActionButtonThemeData.copyWith].
///
/// Typically a [FloatingActionButtonThemeData] is specified as part of the
/// overall [Theme] with [ThemeData.floatingActionButtonTheme].
///
/// All [FloatingActionButtonThemeData] properties are `null` by default.
/// When null, the [FloatingActionButton] will use the values from [ThemeData]
/// if they exist, otherwise it will provide its own defaults.
///
/// See also:
///
/// * [ThemeData], which describes the overall theme information for the
/// application.
class FloatingActionButtonThemeData extends Diagnosticable {
/// Creates a theme that can be used for
/// [ThemeData.floatingActionButtonTheme].
const FloatingActionButtonThemeData({
this.backgroundColor,
this.foregroundColor,
this.elevation,
this.disabledElevation,
this.highlightElevation,
this.shape,
});
/// Color to be used for the unselected, enabled [FloatingActionButton]'s
/// background.
final Color backgroundColor;
/// Color to be used for the unselected, enabled [FloatingActionButton]'s
/// foreground.
final Color foregroundColor;
/// The z-coordinate to be used for the unselected, enabled
/// [FloatingActionButton]'s elevation foreground.
final double elevation;
/// The z-coordinate to be used for the disabled [FloatingActionButton]'s
/// elevation foreground.
final double disabledElevation;
/// The z-coordinate to be used for the selected, enabled
/// [FloatingActionButton]'s elevation foreground.
final double highlightElevation;
/// The shape to be used for the floating action button's [Material].
final ShapeBorder shape;
/// Creates a copy of this object with the given fields replaced with the
/// new values.
FloatingActionButtonThemeData copyWith({
Color backgroundColor,
Color foregroundColor,
double elevation,
double disabledElevation,
double highlightElevation,
ShapeBorder shape,
}) {
return FloatingActionButtonThemeData(
backgroundColor: backgroundColor ?? this.backgroundColor,
foregroundColor: foregroundColor ?? this.foregroundColor,
elevation: elevation ?? this.elevation,
disabledElevation: disabledElevation ?? this.disabledElevation,
highlightElevation: highlightElevation ?? this.highlightElevation,
shape: shape ?? this.shape,
);
}
/// Linearly interpolate between two floating action button themes.
///
/// If both arguments are null then null is returned.
///
/// {@macro dart.ui.shadow.lerp}
static FloatingActionButtonThemeData lerp(FloatingActionButtonThemeData a, FloatingActionButtonThemeData b, double t) {
assert(t != null);
if (a == null && b == null)
return null;
return FloatingActionButtonThemeData(
backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t),
foregroundColor: Color.lerp(a?.foregroundColor, b?.foregroundColor, t),
elevation: lerpDouble(a?.elevation, b?.elevation, t),
disabledElevation: lerpDouble(a?.disabledElevation, b?.disabledElevation, t),
highlightElevation: lerpDouble(a?.highlightElevation, b?.highlightElevation, t),
shape: ShapeBorder.lerp(a?.shape, b?.shape, t),
);
}
@override
int get hashCode {
return hashValues(
backgroundColor,
foregroundColor,
elevation,
disabledElevation,
highlightElevation,
shape,
);
}
@override
bool operator ==(Object other) {
if (identical(this, other))
return true;
if (other.runtimeType != runtimeType)
return false;
final FloatingActionButtonThemeData otherData = other;
return otherData.backgroundColor == backgroundColor
&& otherData.foregroundColor == foregroundColor
&& otherData.elevation == elevation
&& otherData.disabledElevation == disabledElevation
&& otherData.highlightElevation == highlightElevation
&& otherData.shape == shape;
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
const FloatingActionButtonThemeData defaultData = FloatingActionButtonThemeData();
properties.add(DiagnosticsProperty<Color>('backgroundColor', backgroundColor, defaultValue: defaultData.backgroundColor));
properties.add(DiagnosticsProperty<Color>('foregroundColor', foregroundColor, defaultValue: defaultData.foregroundColor));
properties.add(DiagnosticsProperty<double>('elevation', elevation, defaultValue: defaultData.elevation));
properties.add(DiagnosticsProperty<double>('disabledElevation', disabledElevation, defaultValue: defaultData.disabledElevation));
properties.add(DiagnosticsProperty<double>('highlightElevation', highlightElevation, defaultValue: defaultData.highlightElevation));
properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: defaultData.shape));
}
}
......@@ -17,6 +17,7 @@ import 'chip_theme.dart';
import 'color_scheme.dart';
import 'colors.dart';
import 'dialog_theme.dart';
import 'floating_action_button_theme.dart';
import 'ink_splash.dart';
import 'ink_well.dart' show InteractiveInkFeatureFactory;
import 'input_decorator.dart';
......@@ -159,6 +160,7 @@ class ThemeData extends Diagnosticable {
BottomAppBarTheme bottomAppBarTheme,
ColorScheme colorScheme,
DialogTheme dialogTheme,
FloatingActionButtonThemeData floatingActionButtonTheme,
Typography typography,
CupertinoThemeData cupertinoOverrideTheme,
}) {
......@@ -257,6 +259,7 @@ class ThemeData extends Diagnosticable {
labelStyle: textTheme.body2,
);
dialogTheme ??= const DialogTheme();
floatingActionButtonTheme ??= const FloatingActionButtonThemeData();
cupertinoOverrideTheme = cupertinoOverrideTheme?.noDefault();
return ThemeData.raw(
......@@ -308,6 +311,7 @@ class ThemeData extends Diagnosticable {
bottomAppBarTheme: bottomAppBarTheme,
colorScheme: colorScheme,
dialogTheme: dialogTheme,
floatingActionButtonTheme: floatingActionButtonTheme,
typography: typography,
cupertinoOverrideTheme: cupertinoOverrideTheme,
);
......@@ -372,6 +376,7 @@ class ThemeData extends Diagnosticable {
@required this.bottomAppBarTheme,
@required this.colorScheme,
@required this.dialogTheme,
@required this.floatingActionButtonTheme,
@required this.typography,
@required this.cupertinoOverrideTheme,
}) : assert(brightness != null),
......@@ -421,6 +426,7 @@ class ThemeData extends Diagnosticable {
assert(bottomAppBarTheme != null),
assert(colorScheme != null),
assert(dialogTheme != null),
assert(floatingActionButtonTheme != null),
assert(typography != null);
// Warning: make sure these properties are in the exact same order as in
......@@ -662,6 +668,10 @@ class ThemeData extends Diagnosticable {
/// A theme for customizing the shape of a dialog.
final DialogTheme dialogTheme;
/// A theme for customizing the shape, elevation, and color of a
/// [FloatingActionButton].
final FloatingActionButtonThemeData floatingActionButtonTheme;
/// The color and geometry [TextTheme] values used to configure [textTheme],
/// [primaryTextTheme], and [accentTextTheme].
final Typography typography;
......@@ -728,6 +738,7 @@ class ThemeData extends Diagnosticable {
BottomAppBarTheme bottomAppBarTheme,
ColorScheme colorScheme,
DialogTheme dialogTheme,
FloatingActionButtonThemeData floatingActionButtonTheme,
Typography typography,
CupertinoThemeData cupertinoOverrideTheme,
}) {
......@@ -781,6 +792,7 @@ class ThemeData extends Diagnosticable {
bottomAppBarTheme: bottomAppBarTheme ?? this.bottomAppBarTheme,
colorScheme: colorScheme ?? this.colorScheme,
dialogTheme: dialogTheme ?? this.dialogTheme,
floatingActionButtonTheme: floatingActionButtonTheme ?? this.floatingActionButtonTheme,
typography: typography ?? this.typography,
cupertinoOverrideTheme: cupertinoOverrideTheme ?? this.cupertinoOverrideTheme,
);
......@@ -912,6 +924,7 @@ class ThemeData extends Diagnosticable {
bottomAppBarTheme: BottomAppBarTheme.lerp(a.bottomAppBarTheme, b.bottomAppBarTheme, t),
colorScheme: ColorScheme.lerp(a.colorScheme, b.colorScheme, t),
dialogTheme: DialogTheme.lerp(a.dialogTheme, b.dialogTheme, t),
floatingActionButtonTheme: FloatingActionButtonThemeData.lerp(a.floatingActionButtonTheme, b.floatingActionButtonTheme, t),
typography: Typography.lerp(a.typography, b.typography, t),
cupertinoOverrideTheme: t < 0.5 ? a.cupertinoOverrideTheme : b.cupertinoOverrideTheme,
);
......@@ -973,6 +986,7 @@ class ThemeData extends Diagnosticable {
(otherData.bottomAppBarTheme == bottomAppBarTheme) &&
(otherData.colorScheme == colorScheme) &&
(otherData.dialogTheme == dialogTheme) &&
(otherData.floatingActionButtonTheme == floatingActionButtonTheme) &&
(otherData.typography == typography) &&
(otherData.cupertinoOverrideTheme == cupertinoOverrideTheme);
}
......@@ -1034,6 +1048,7 @@ class ThemeData extends Diagnosticable {
bottomAppBarTheme,
colorScheme,
dialogTheme,
floatingActionButtonTheme,
typography,
cupertinoOverrideTheme,
),
......@@ -1090,6 +1105,7 @@ class ThemeData extends Diagnosticable {
properties.add(DiagnosticsProperty<BottomAppBarTheme>('bottomAppBarTheme', bottomAppBarTheme, defaultValue: defaultData.bottomAppBarTheme));
properties.add(DiagnosticsProperty<ColorScheme>('colorScheme', colorScheme, defaultValue: defaultData.colorScheme));
properties.add(DiagnosticsProperty<DialogTheme>('dialogTheme', dialogTheme, defaultValue: defaultData.dialogTheme));
properties.add(DiagnosticsProperty<FloatingActionButtonThemeData>('floatingActionButtonThemeData', floatingActionButtonTheme, defaultValue: defaultData.floatingActionButtonTheme));
properties.add(DiagnosticsProperty<Typography>('typography', typography, defaultValue: defaultData.typography));
properties.add(DiagnosticsProperty<CupertinoThemeData>('cupertinoOverrideTheme', cupertinoOverrideTheme, defaultValue: defaultData.cupertinoOverrideTheme));
}
......
......@@ -110,11 +110,6 @@ void main() {
expect(find.text('Add'), findsOneWidget);
});
testWidgets('Floating Action Button elevation when highlighted - defaults', (WidgetTester tester) async {
expect(const FloatingActionButton(onPressed: null).highlightElevation, 12.0);
expect(const FloatingActionButton(onPressed: null, highlightElevation: 0.0).highlightElevation, 0.0);
});
testWidgets('Floating Action Button elevation when highlighted - effect', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
......@@ -153,9 +148,33 @@ void main() {
});
testWidgets('Floating Action Button elevation when disabled - defaults', (WidgetTester tester) async {
expect(FloatingActionButton(onPressed: () { }).disabledElevation, 6.0);
expect(const FloatingActionButton(onPressed: null).disabledElevation, 6.0);
expect(FloatingActionButton(onPressed: () { }, disabledElevation: 0.0).disabledElevation, 0.0);
await tester.pumpWidget(
const MaterialApp(
home: Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: null,
),
),
),
);
// Disabled elevation defaults to regular default elevation.
expect(tester.widget<PhysicalShape>(find.byType(PhysicalShape)).elevation, 6.0);
});
testWidgets('Floating Action Button elevation when disabled - override', (WidgetTester tester) async {
await tester.pumpWidget(
const MaterialApp(
home: Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: null,
disabledElevation: 0,
),
),
),
);
expect(tester.widget<PhysicalShape>(find.byType(PhysicalShape)).elevation, 0.0);
});
testWidgets('Floating Action Button elevation when disabled - effect', (WidgetTester tester) async {
......@@ -294,8 +313,14 @@ void main() {
return tester.widget<FloatingActionButton>(fabFinder);
}
final Finder materialButtonFinder = find.byType(RawMaterialButton);
RawMaterialButton getRawMaterialButtonWidget() {
return tester.widget<RawMaterialButton>(materialButtonFinder);
}
expect(getFabWidget().isExtended, false);
expect(getFabWidget().shape, const CircleBorder());
expect(getRawMaterialButtonWidget().shape, const CircleBorder());
await tester.pumpWidget(
MaterialApp(
......@@ -313,7 +338,7 @@ void main() {
);
expect(getFabWidget().isExtended, true);
expect(getFabWidget().shape, const StadiumBorder());
expect(getRawMaterialButtonWidget().shape, const StadiumBorder());
expect(find.text('label'), findsOneWidget);
expect(find.byType(Icon), findsOneWidget);
......@@ -345,6 +370,12 @@ void main() {
return tester.widget<FloatingActionButton>(fabFinder);
}
final Finder materialButtonFinder = find.byType(RawMaterialButton);
RawMaterialButton getRawMaterialButtonWidget() {
return tester.widget<RawMaterialButton>(materialButtonFinder);
}
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
......@@ -360,7 +391,7 @@ void main() {
);
expect(getFabWidget().isExtended, true);
expect(getFabWidget().shape, const StadiumBorder());
expect(getRawMaterialButtonWidget().shape, const StadiumBorder());
expect(find.text('label'), findsOneWidget);
expect(find.byType(Icon), findsNothing);
......
// Copyright 2019 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/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
test('FloatingActionButtonThemeData copyWith, ==, hashCode basics', () {
expect(const FloatingActionButtonThemeData(), const FloatingActionButtonThemeData().copyWith());
expect(const FloatingActionButtonThemeData().hashCode, const FloatingActionButtonThemeData().copyWith().hashCode);
});
testWidgets('Default values are used when no FloatingActionButton or FloatingActionButtonThemeData properties are specified', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () { },
child: const Icon(Icons.add),
),
),
));
// The color scheme values are guaranteed to be non null since the default
// [ThemeData] creates it with [ColorScheme.fromSwatch].
expect(_getRawMaterialButton(tester).fillColor, ThemeData().colorScheme.secondary);
expect(_getRichText(tester).text.style.color, ThemeData().colorScheme.onSecondary);
// These defaults come directly from the [FloatingActionButton].
expect(_getRawMaterialButton(tester).elevation, 6);
expect(_getRawMaterialButton(tester).highlightElevation, 12);
expect(_getRawMaterialButton(tester).shape, const CircleBorder());
});
testWidgets('FloatingActionButtonThemeData values are used when no FloatingActionButton properties are specified', (WidgetTester tester) async {
const Color backgroundColor = Color(0xBEEFBEEF);
const Color foregroundColor = Color(0xFACEFACE);
const double elevation = 7;
const double disabledElevation = 1;
const double highlightElevation = 13;
const ShapeBorder shape = StadiumBorder();
await tester.pumpWidget(MaterialApp(
theme: ThemeData().copyWith(
floatingActionButtonTheme: const FloatingActionButtonThemeData(
backgroundColor: backgroundColor,
foregroundColor: foregroundColor,
elevation: elevation,
disabledElevation: disabledElevation,
highlightElevation: highlightElevation,
shape: shape,
)
),
home: Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () { },
child: const Icon(Icons.add),
),
),
));
expect(_getRawMaterialButton(tester).fillColor, backgroundColor);
expect(_getRichText(tester).text.style.color, foregroundColor);
expect(_getRawMaterialButton(tester).elevation, elevation);
expect(_getRawMaterialButton(tester).disabledElevation, disabledElevation);
expect(_getRawMaterialButton(tester).highlightElevation, highlightElevation);
expect(_getRawMaterialButton(tester).shape, shape);
});
testWidgets('FloatingActionButton values take priority over FloatingActionButtonThemeData values when both properties are specified', (WidgetTester tester) async {
const Color backgroundColor = Color(0xBEEFBEEF);
const Color foregroundColor = Color(0xFACEFACE);
const double elevation = 7;
const double disabledElevation = 1;
const double highlightElevation = 13;
const ShapeBorder shape = StadiumBorder();
await tester.pumpWidget(MaterialApp(
theme: ThemeData().copyWith(
floatingActionButtonTheme: const FloatingActionButtonThemeData(
backgroundColor: Color(0xCAFECAFE),
foregroundColor: Color(0xFEEDFEED),
elevation: 23,
disabledElevation: 11,
highlightElevation: 43,
shape: BeveledRectangleBorder(),
),
),
home: Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () { },
child: const Icon(Icons.add),
backgroundColor: backgroundColor,
foregroundColor: foregroundColor,
elevation: elevation,
disabledElevation: disabledElevation,
highlightElevation: highlightElevation,
shape: shape,
),
),
));
expect(_getRawMaterialButton(tester).fillColor, backgroundColor);
expect(_getRichText(tester).text.style.color, foregroundColor);
expect(_getRawMaterialButton(tester).elevation, elevation);
expect(_getRawMaterialButton(tester).disabledElevation, disabledElevation);
expect(_getRawMaterialButton(tester).highlightElevation, highlightElevation);
expect(_getRawMaterialButton(tester).shape, shape);
});
testWidgets('FloatingActionButton foreground color uses iconAccentTheme if no widget or widget theme color is specified', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Scaffold(
floatingActionButton: Theme(
data: ThemeData().copyWith(
accentIconTheme: const IconThemeData(color: Color(0xFACEFACE)),
),
child: FloatingActionButton(
onPressed: () { },
child: const Icon(Icons.add),
),
),
),
));
expect(_getRichText(tester).text.style.color, const Color(0xFACEFACE));
});
testWidgets('FloatingActionButton uses a custom shape when specified in the theme', (WidgetTester tester) async {
const ShapeBorder customShape = BeveledRectangleBorder();
await tester.pumpWidget(MaterialApp(
home: Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () { },
shape: customShape,
),
),
));
expect(_getRawMaterialButton(tester).shape, customShape);
});
testWidgets('default FloatingActionButton debugFillProperties', (WidgetTester tester) async {
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
const FloatingActionButtonThemeData ().debugFillProperties(builder);
final List<String> description = builder.properties
.where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
.map((DiagnosticsNode node) => node.toString())
.toList();
expect(description, <String>[]);
});
testWidgets('Material implements debugFillProperties', (WidgetTester tester) async {
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
const FloatingActionButtonThemeData(
backgroundColor: Color(0xCAFECAFE),
foregroundColor: Color(0xFEEDFEED),
elevation: 23,
disabledElevation: 11,
highlightElevation: 43,
shape: BeveledRectangleBorder(),
).debugFillProperties(builder);
final List<String> description = builder.properties
.where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
.map((DiagnosticsNode node) => node.toString())
.toList();
expect(description, <String>[
'backgroundColor: Color(0xcafecafe)',
'foregroundColor: Color(0xfeedfeed)',
'elevation: 23.0',
'disabledElevation: 11.0',
'highlightElevation: 43.0',
'shape: BeveledRectangleBorder(BorderSide(Color(0xff000000), 0.0, BorderStyle.none), BorderRadius.zero)',
]);
});
}
RawMaterialButton _getRawMaterialButton(WidgetTester tester) {
return tester.widget<RawMaterialButton>(
find.descendant(
of: find.byType(FloatingActionButton),
matching: find.byType(RawMaterialButton),
),
);
}
RichText _getRichText(WidgetTester tester) {
return tester.widget<RichText>(
find.descendant(
of: find.byType(FloatingActionButton),
matching: find.byType(RichText),
),
);
}
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