Unverified Commit 37c414dd authored by Rami's avatar Rami Committed by GitHub

Allow for customizing and theming extended FAB's TextStyle (#87498)

parent 22436cca
...@@ -172,6 +172,7 @@ class FloatingActionButton extends StatelessWidget { ...@@ -172,6 +172,7 @@ class FloatingActionButton extends StatelessWidget {
_extendedLabel = null, _extendedLabel = null,
extendedIconLabelSpacing = null, extendedIconLabelSpacing = null,
extendedPadding = null, extendedPadding = null,
extendedTextStyle = null,
super(key: key); super(key: key);
/// Creates a small circular floating action button. /// Creates a small circular floating action button.
...@@ -219,6 +220,7 @@ class FloatingActionButton extends StatelessWidget { ...@@ -219,6 +220,7 @@ class FloatingActionButton extends StatelessWidget {
_extendedLabel = null, _extendedLabel = null,
extendedIconLabelSpacing = null, extendedIconLabelSpacing = null,
extendedPadding = null, extendedPadding = null,
extendedTextStyle = null,
super(key: key); super(key: key);
/// Creates a large circular floating action button. /// Creates a large circular floating action button.
...@@ -266,6 +268,7 @@ class FloatingActionButton extends StatelessWidget { ...@@ -266,6 +268,7 @@ class FloatingActionButton extends StatelessWidget {
_extendedLabel = null, _extendedLabel = null,
extendedIconLabelSpacing = null, extendedIconLabelSpacing = null,
extendedPadding = null, extendedPadding = null,
extendedTextStyle = null,
super(key: key); super(key: key);
/// Creates a wider [StadiumBorder]-shaped floating action button with /// Creates a wider [StadiumBorder]-shaped floating action button with
...@@ -298,6 +301,7 @@ class FloatingActionButton extends StatelessWidget { ...@@ -298,6 +301,7 @@ class FloatingActionButton extends StatelessWidget {
this.autofocus = false, this.autofocus = false,
this.extendedIconLabelSpacing, this.extendedIconLabelSpacing,
this.extendedPadding, this.extendedPadding,
this.extendedTextStyle,
Widget? icon, Widget? icon,
required Widget label, required Widget label,
this.enableFeedback, this.enableFeedback,
...@@ -530,6 +534,13 @@ class FloatingActionButton extends StatelessWidget { ...@@ -530,6 +534,13 @@ class FloatingActionButton extends StatelessWidget {
/// provided, and `EdgeInsetsDirectional.only(start: 20.0, end: 20.0)` if not. /// provided, and `EdgeInsetsDirectional.only(start: 20.0, end: 20.0)` if not.
final EdgeInsetsGeometry? extendedPadding; final EdgeInsetsGeometry? extendedPadding;
/// The text style for an extended [FloatingActionButton]'s label.
///
/// If null, [FloatingActionButtonThemeData.extendedTextStyle] is used. If
/// that is also null, then [TextTheme.button] with a letter spacing of 1.2
/// is used.
final TextStyle? extendedTextStyle;
final _FloatingActionButtonType _floatingActionButtonType; final _FloatingActionButtonType _floatingActionButtonType;
final Widget? _extendedLabel; final Widget? _extendedLabel;
...@@ -580,10 +591,9 @@ class FloatingActionButton extends StatelessWidget { ...@@ -580,10 +591,9 @@ class FloatingActionButton extends StatelessWidget {
?? theme.materialTapTargetSize; ?? theme.materialTapTargetSize;
final bool enableFeedback = this.enableFeedback final bool enableFeedback = this.enableFeedback
?? floatingActionButtonTheme.enableFeedback ?? true; ?? floatingActionButtonTheme.enableFeedback ?? true;
final TextStyle textStyle = theme.textTheme.button!.copyWith( final TextStyle extendedTextStyle = (this.extendedTextStyle
color: foregroundColor, ?? floatingActionButtonTheme.extendedTextStyle
letterSpacing: 1.2, ?? theme.textTheme.button!.copyWith(letterSpacing: 1.2)).copyWith(color: foregroundColor);
);
final ShapeBorder shape = this.shape final ShapeBorder shape = this.shape
?? floatingActionButtonTheme.shape ?? floatingActionButtonTheme.shape
?? (isExtended ? _defaultExtendedShape : _defaultShape); ?? (isExtended ? _defaultExtendedShape : _defaultShape);
...@@ -644,7 +654,7 @@ class FloatingActionButton extends StatelessWidget { ...@@ -644,7 +654,7 @@ class FloatingActionButton extends StatelessWidget {
focusColor: focusColor, focusColor: focusColor,
hoverColor: hoverColor, hoverColor: hoverColor,
splashColor: splashColor, splashColor: splashColor,
textStyle: textStyle, textStyle: extendedTextStyle,
shape: shape, shape: shape,
clipBehavior: clipBehavior, clipBehavior: clipBehavior,
focusNode: focusNode, focusNode: focusNode,
......
...@@ -49,6 +49,7 @@ class FloatingActionButtonThemeData with Diagnosticable { ...@@ -49,6 +49,7 @@ class FloatingActionButtonThemeData with Diagnosticable {
this.extendedSizeConstraints, this.extendedSizeConstraints,
this.extendedIconLabelSpacing, this.extendedIconLabelSpacing,
this.extendedPadding, this.extendedPadding,
this.extendedTextStyle,
}); });
/// Color to be used for the unselected, enabled [FloatingActionButton]'s /// Color to be used for the unselected, enabled [FloatingActionButton]'s
...@@ -121,6 +122,9 @@ class FloatingActionButtonThemeData with Diagnosticable { ...@@ -121,6 +122,9 @@ class FloatingActionButtonThemeData with Diagnosticable {
/// The padding for an extended [FloatingActionButton]'s content. /// The padding for an extended [FloatingActionButton]'s content.
final EdgeInsetsGeometry? extendedPadding; final EdgeInsetsGeometry? extendedPadding;
/// The text style for an extended [FloatingActionButton]'s label.
final TextStyle? extendedTextStyle;
/// Creates a copy of this object with the given fields replaced with the /// Creates a copy of this object with the given fields replaced with the
/// new values. /// new values.
FloatingActionButtonThemeData copyWith({ FloatingActionButtonThemeData copyWith({
...@@ -142,6 +146,7 @@ class FloatingActionButtonThemeData with Diagnosticable { ...@@ -142,6 +146,7 @@ class FloatingActionButtonThemeData with Diagnosticable {
BoxConstraints? extendedSizeConstraints, BoxConstraints? extendedSizeConstraints,
double? extendedIconLabelSpacing, double? extendedIconLabelSpacing,
EdgeInsetsGeometry? extendedPadding, EdgeInsetsGeometry? extendedPadding,
TextStyle? extendedTextStyle,
}) { }) {
return FloatingActionButtonThemeData( return FloatingActionButtonThemeData(
foregroundColor: foregroundColor ?? this.foregroundColor, foregroundColor: foregroundColor ?? this.foregroundColor,
...@@ -162,6 +167,7 @@ class FloatingActionButtonThemeData with Diagnosticable { ...@@ -162,6 +167,7 @@ class FloatingActionButtonThemeData with Diagnosticable {
extendedSizeConstraints: extendedSizeConstraints ?? this.extendedSizeConstraints, extendedSizeConstraints: extendedSizeConstraints ?? this.extendedSizeConstraints,
extendedIconLabelSpacing: extendedIconLabelSpacing ?? this.extendedIconLabelSpacing, extendedIconLabelSpacing: extendedIconLabelSpacing ?? this.extendedIconLabelSpacing,
extendedPadding: extendedPadding ?? this.extendedPadding, extendedPadding: extendedPadding ?? this.extendedPadding,
extendedTextStyle: extendedTextStyle ?? this.extendedTextStyle,
); );
} }
...@@ -193,6 +199,7 @@ class FloatingActionButtonThemeData with Diagnosticable { ...@@ -193,6 +199,7 @@ class FloatingActionButtonThemeData with Diagnosticable {
extendedSizeConstraints: BoxConstraints.lerp(a?.extendedSizeConstraints, b?.extendedSizeConstraints, t), extendedSizeConstraints: BoxConstraints.lerp(a?.extendedSizeConstraints, b?.extendedSizeConstraints, t),
extendedIconLabelSpacing: lerpDouble(a?.extendedIconLabelSpacing, b?.extendedIconLabelSpacing, t), extendedIconLabelSpacing: lerpDouble(a?.extendedIconLabelSpacing, b?.extendedIconLabelSpacing, t),
extendedPadding: EdgeInsetsGeometry.lerp(a?.extendedPadding, b?.extendedPadding, t), extendedPadding: EdgeInsetsGeometry.lerp(a?.extendedPadding, b?.extendedPadding, t),
extendedTextStyle: TextStyle.lerp(a?.extendedTextStyle, b?.extendedTextStyle, t),
); );
} }
...@@ -217,6 +224,7 @@ class FloatingActionButtonThemeData with Diagnosticable { ...@@ -217,6 +224,7 @@ class FloatingActionButtonThemeData with Diagnosticable {
extendedSizeConstraints, extendedSizeConstraints,
extendedIconLabelSpacing, extendedIconLabelSpacing,
extendedPadding, extendedPadding,
extendedTextStyle,
); );
} }
...@@ -244,7 +252,8 @@ class FloatingActionButtonThemeData with Diagnosticable { ...@@ -244,7 +252,8 @@ class FloatingActionButtonThemeData with Diagnosticable {
&& other.largeSizeConstraints == largeSizeConstraints && other.largeSizeConstraints == largeSizeConstraints
&& other.extendedSizeConstraints == extendedSizeConstraints && other.extendedSizeConstraints == extendedSizeConstraints
&& other.extendedIconLabelSpacing == extendedIconLabelSpacing && other.extendedIconLabelSpacing == extendedIconLabelSpacing
&& other.extendedPadding == extendedPadding; && other.extendedPadding == extendedPadding
&& other.extendedTextStyle == extendedTextStyle;
} }
@override @override
...@@ -269,5 +278,6 @@ class FloatingActionButtonThemeData with Diagnosticable { ...@@ -269,5 +278,6 @@ class FloatingActionButtonThemeData with Diagnosticable {
properties.add(DiagnosticsProperty<BoxConstraints>('extendedSizeConstraints', extendedSizeConstraints, defaultValue: null)); properties.add(DiagnosticsProperty<BoxConstraints>('extendedSizeConstraints', extendedSizeConstraints, defaultValue: null));
properties.add(DoubleProperty('extendedIconLabelSpacing', extendedIconLabelSpacing, defaultValue: null)); properties.add(DoubleProperty('extendedIconLabelSpacing', extendedIconLabelSpacing, defaultValue: null));
properties.add(DiagnosticsProperty<EdgeInsetsGeometry>('extendedPadding', extendedPadding, defaultValue: null)); properties.add(DiagnosticsProperty<EdgeInsetsGeometry>('extendedPadding', extendedPadding, defaultValue: null));
properties.add(DiagnosticsProperty<TextStyle>('extendedTextStyle', extendedTextStyle, defaultValue: null));
} }
} }
...@@ -1023,6 +1023,33 @@ void main() { ...@@ -1023,6 +1023,33 @@ void main() {
expect(tester.getTopRight(find.byType(FloatingActionButton)).dx - tester.getTopRight(find.byKey(labelKey)).dx, padding.end); expect(tester.getTopRight(find.byType(FloatingActionButton)).dx - tester.getTopRight(find.byKey(labelKey)).dx, padding.end);
}); });
testWidgets('FloatingActionButton.extended can customize text style', (WidgetTester tester) async {
const Key labelKey = Key('label');
const TextStyle style = TextStyle(letterSpacing: 2.0);
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
floatingActionButton: FloatingActionButton.extended(
label: const Text('', key: labelKey),
icon: const Icon(Icons.add),
extendedTextStyle: style,
onPressed: () {},
),
),
),
);
final RawMaterialButton rawMaterialButton = tester.widget<RawMaterialButton>(
find.descendant(
of: find.byType(FloatingActionButton),
matching: find.byType(RawMaterialButton),
),
);
// The color comes from the default color scheme's onSecondary value.
expect(rawMaterialButton.textStyle, style.copyWith(color: const Color(0xffffffff)));
});
group('feedback', () { group('feedback', () {
late FeedbackTester feedback; late FeedbackTester feedback;
......
...@@ -176,12 +176,13 @@ void main() { ...@@ -176,12 +176,13 @@ void main() {
expect(_getRawMaterialButton(tester).constraints, constraints); expect(_getRawMaterialButton(tester).constraints, constraints);
}); });
testWidgets('FloatingActionButton.extended uses custom constraints and spacing when specified in the theme', (WidgetTester tester) async { testWidgets('FloatingActionButton.extended uses custom properties when specified in the theme', (WidgetTester tester) async {
const Key iconKey = Key('icon'); const Key iconKey = Key('icon');
const Key labelKey = Key('label'); const Key labelKey = Key('label');
const BoxConstraints constraints = BoxConstraints.tightFor(height: 100.0); const BoxConstraints constraints = BoxConstraints.tightFor(height: 100.0);
const double iconLabelSpacing = 33.0; const double iconLabelSpacing = 33.0;
const EdgeInsetsDirectional padding = EdgeInsetsDirectional.only(start: 5.0, end: 6.0); const EdgeInsetsDirectional padding = EdgeInsetsDirectional.only(start: 5.0, end: 6.0);
const TextStyle textStyle = TextStyle(letterSpacing: 2.0);
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: ThemeData().copyWith( theme: ThemeData().copyWith(
...@@ -189,6 +190,7 @@ void main() { ...@@ -189,6 +190,7 @@ void main() {
extendedSizeConstraints: constraints, extendedSizeConstraints: constraints,
extendedIconLabelSpacing: iconLabelSpacing, extendedIconLabelSpacing: iconLabelSpacing,
extendedPadding: padding, extendedPadding: padding,
extendedTextStyle: textStyle,
), ),
), ),
home: Scaffold( home: Scaffold(
...@@ -204,19 +206,23 @@ void main() { ...@@ -204,19 +206,23 @@ void main() {
expect(tester.getTopLeft(find.byKey(labelKey)).dx - tester.getTopRight(find.byKey(iconKey)).dx, iconLabelSpacing); expect(tester.getTopLeft(find.byKey(labelKey)).dx - tester.getTopRight(find.byKey(iconKey)).dx, iconLabelSpacing);
expect(tester.getTopLeft(find.byKey(iconKey)).dx - tester.getTopLeft(find.byType(FloatingActionButton)).dx, padding.start); expect(tester.getTopLeft(find.byKey(iconKey)).dx - tester.getTopLeft(find.byType(FloatingActionButton)).dx, padding.start);
expect(tester.getTopRight(find.byType(FloatingActionButton)).dx - tester.getTopRight(find.byKey(labelKey)).dx, padding.end); expect(tester.getTopRight(find.byType(FloatingActionButton)).dx - tester.getTopRight(find.byKey(labelKey)).dx, padding.end);
// The color comes from the default color scheme's onSecondary value.
expect(_getRawMaterialButton(tester).textStyle, textStyle.copyWith(color: const Color(0xffffffff)));
}); });
testWidgets('FloatingActionButton.extended spacing takes priority over FloatingActionButtonThemeData spacing', (WidgetTester tester) async { testWidgets('FloatingActionButton.extended custom properties takes priority over FloatingActionButtonThemeData spacing', (WidgetTester tester) async {
const Key iconKey = Key('icon'); const Key iconKey = Key('icon');
const Key labelKey = Key('label'); const Key labelKey = Key('label');
const double iconLabelSpacing = 33.0; const double iconLabelSpacing = 33.0;
const EdgeInsetsDirectional padding = EdgeInsetsDirectional.only(start: 5.0, end: 6.0); const EdgeInsetsDirectional padding = EdgeInsetsDirectional.only(start: 5.0, end: 6.0);
const TextStyle textStyle = TextStyle(letterSpacing: 2.0);
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: ThemeData().copyWith( theme: ThemeData().copyWith(
floatingActionButtonTheme: const FloatingActionButtonThemeData( floatingActionButtonTheme: const FloatingActionButtonThemeData(
extendedIconLabelSpacing: 25.0, extendedIconLabelSpacing: 25.0,
extendedPadding: EdgeInsetsDirectional.only(start: 7.0, end: 8.0), extendedPadding: EdgeInsetsDirectional.only(start: 7.0, end: 8.0),
extendedTextStyle: TextStyle(letterSpacing: 3.0),
), ),
), ),
home: Scaffold( home: Scaffold(
...@@ -226,6 +232,7 @@ void main() { ...@@ -226,6 +232,7 @@ void main() {
icon: const Icon(Icons.add, key: iconKey), icon: const Icon(Icons.add, key: iconKey),
extendedIconLabelSpacing: iconLabelSpacing, extendedIconLabelSpacing: iconLabelSpacing,
extendedPadding: padding, extendedPadding: padding,
extendedTextStyle: textStyle,
), ),
), ),
)); ));
...@@ -233,6 +240,8 @@ void main() { ...@@ -233,6 +240,8 @@ void main() {
expect(tester.getTopLeft(find.byKey(labelKey)).dx - tester.getTopRight(find.byKey(iconKey)).dx, iconLabelSpacing); expect(tester.getTopLeft(find.byKey(labelKey)).dx - tester.getTopRight(find.byKey(iconKey)).dx, iconLabelSpacing);
expect(tester.getTopLeft(find.byKey(iconKey)).dx - tester.getTopLeft(find.byType(FloatingActionButton)).dx, padding.start); expect(tester.getTopLeft(find.byKey(iconKey)).dx - tester.getTopLeft(find.byType(FloatingActionButton)).dx, padding.start);
expect(tester.getTopRight(find.byType(FloatingActionButton)).dx - tester.getTopRight(find.byKey(labelKey)).dx, padding.end); expect(tester.getTopRight(find.byType(FloatingActionButton)).dx - tester.getTopRight(find.byKey(labelKey)).dx, padding.end);
// The color comes from the default color scheme's onSecondary value.
expect(_getRawMaterialButton(tester).textStyle, textStyle.copyWith(color: const Color(0xffffffff)));
}); });
testWidgets('default FloatingActionButton debugFillProperties', (WidgetTester tester) async { testWidgets('default FloatingActionButton debugFillProperties', (WidgetTester tester) async {
...@@ -268,6 +277,7 @@ void main() { ...@@ -268,6 +277,7 @@ void main() {
extendedSizeConstraints: BoxConstraints(minHeight: 103.0, maxHeight: 103.0), extendedSizeConstraints: BoxConstraints(minHeight: 103.0, maxHeight: 103.0),
extendedIconLabelSpacing: 12, extendedIconLabelSpacing: 12,
extendedPadding: EdgeInsetsDirectional.only(start: 7.0, end: 8.0), extendedPadding: EdgeInsetsDirectional.only(start: 7.0, end: 8.0),
extendedTextStyle: TextStyle(letterSpacing: 2.0),
).debugFillProperties(builder); ).debugFillProperties(builder);
final List<String> description = builder.properties final List<String> description = builder.properties
...@@ -294,6 +304,7 @@ void main() { ...@@ -294,6 +304,7 @@ void main() {
'extendedSizeConstraints: BoxConstraints(0.0<=w<=Infinity, h=103.0)', 'extendedSizeConstraints: BoxConstraints(0.0<=w<=Infinity, h=103.0)',
'extendedIconLabelSpacing: 12.0', 'extendedIconLabelSpacing: 12.0',
'extendedPadding: EdgeInsetsDirectional(7.0, 0.0, 8.0, 0.0)', 'extendedPadding: EdgeInsetsDirectional(7.0, 0.0, 8.0, 0.0)',
'extendedTextStyle: TextStyle(inherit: true, letterSpacing: 2.0)',
]); ]);
}); });
} }
......
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