Allow for customizing and theming of extended FAB content padding (#87062)
diff --git a/packages/flutter/lib/src/material/floating_action_button.dart b/packages/flutter/lib/src/material/floating_action_button.dart
index 4dc6308..9f94800 100644
--- a/packages/flutter/lib/src/material/floating_action_button.dart
+++ b/packages/flutter/lib/src/material/floating_action_button.dart
@@ -171,6 +171,7 @@
_floatingActionButtonType = mini ? _FloatingActionButtonType.small : _FloatingActionButtonType.regular,
_extendedLabel = null,
extendedIconLabelSpacing = null,
+ extendedPadding = null,
super(key: key);
/// Creates a small circular floating action button.
@@ -217,6 +218,7 @@
isExtended = false,
_extendedLabel = null,
extendedIconLabelSpacing = null,
+ extendedPadding = null,
super(key: key);
/// Creates a large circular floating action button.
@@ -263,6 +265,7 @@
isExtended = false,
_extendedLabel = null,
extendedIconLabelSpacing = null,
+ extendedPadding = null,
super(key: key);
/// Creates a wider [StadiumBorder]-shaped floating action button with
@@ -294,6 +297,7 @@
this.focusNode,
this.autofocus = false,
this.extendedIconLabelSpacing,
+ this.extendedPadding,
Widget? icon,
required Widget label,
this.enableFeedback,
@@ -518,6 +522,14 @@
/// If that is also null, the default is 8.0.
final double? extendedIconLabelSpacing;
+ /// The padding for an extended [FloatingActionButton]'s content.
+ ///
+ /// If null, [FloatingActionButtonThemeData.extendedPadding] is used. If that
+ /// is also null, the default is
+ /// `EdgeInsetsDirectional.only(start: 16.0, end: 20.0)` if an icon is
+ /// provided, and `EdgeInsetsDirectional.only(start: 20.0, end: 20.0)` if not.
+ final EdgeInsetsGeometry? extendedPadding;
+
final _FloatingActionButtonType _floatingActionButtonType;
final Widget? _extendedLabel;
@@ -596,16 +608,23 @@
case _FloatingActionButtonType.extended:
sizeConstraints = floatingActionButtonTheme.extendedSizeConstraints ?? _kExtendedSizeConstraints;
final double iconLabelSpacing = extendedIconLabelSpacing ?? floatingActionButtonTheme.extendedIconLabelSpacing ?? 8.0;
- const Widget width20 = SizedBox(width: 20.0);
- const Widget width16 = SizedBox(width: 16.0);
+ final EdgeInsetsGeometry padding = extendedPadding
+ ?? floatingActionButtonTheme.extendedPadding
+ ?? EdgeInsetsDirectional.only(start: child != null && isExtended ? 16.0 : 20.0, end: 20.0);
resolvedChild = _ChildOverflowBox(
- child: Row(
- mainAxisSize: MainAxisSize.min,
- children: child == null
- ? <Widget>[width20, _extendedLabel!, width20]
- : isExtended
- ? <Widget>[width16, child!, SizedBox(width: iconLabelSpacing), _extendedLabel!, width20]
- : <Widget>[width20, child!, width20],
+ child: Padding(
+ padding: padding,
+ child: Row(
+ mainAxisSize: MainAxisSize.min,
+ children: <Widget>[
+ if (child != null)
+ child!,
+ if (child != null && isExtended)
+ SizedBox(width: iconLabelSpacing),
+ if (isExtended)
+ _extendedLabel!,
+ ],
+ ),
),
);
break;
diff --git a/packages/flutter/lib/src/material/floating_action_button_theme.dart b/packages/flutter/lib/src/material/floating_action_button_theme.dart
index d020b01..8e4f6ec 100644
--- a/packages/flutter/lib/src/material/floating_action_button_theme.dart
+++ b/packages/flutter/lib/src/material/floating_action_button_theme.dart
@@ -48,6 +48,7 @@
this.largeSizeConstraints,
this.extendedSizeConstraints,
this.extendedIconLabelSpacing,
+ this.extendedPadding,
});
/// Color to be used for the unselected, enabled [FloatingActionButton]'s
@@ -117,6 +118,9 @@
/// [FloatingActionButton].
final double? extendedIconLabelSpacing;
+ /// The padding for an extended [FloatingActionButton]'s content.
+ final EdgeInsetsGeometry? extendedPadding;
+
/// Creates a copy of this object with the given fields replaced with the
/// new values.
FloatingActionButtonThemeData copyWith({
@@ -137,6 +141,7 @@
BoxConstraints? largeSizeConstraints,
BoxConstraints? extendedSizeConstraints,
double? extendedIconLabelSpacing,
+ EdgeInsetsGeometry? extendedPadding,
}) {
return FloatingActionButtonThemeData(
foregroundColor: foregroundColor ?? this.foregroundColor,
@@ -156,6 +161,7 @@
largeSizeConstraints: largeSizeConstraints ?? this.largeSizeConstraints,
extendedSizeConstraints: extendedSizeConstraints ?? this.extendedSizeConstraints,
extendedIconLabelSpacing: extendedIconLabelSpacing ?? this.extendedIconLabelSpacing,
+ extendedPadding: extendedPadding ?? this.extendedPadding,
);
}
@@ -186,6 +192,7 @@
largeSizeConstraints: BoxConstraints.lerp(a?.largeSizeConstraints, b?.largeSizeConstraints, t),
extendedSizeConstraints: BoxConstraints.lerp(a?.extendedSizeConstraints, b?.extendedSizeConstraints, t),
extendedIconLabelSpacing: lerpDouble(a?.extendedIconLabelSpacing, b?.extendedIconLabelSpacing, t),
+ extendedPadding: EdgeInsetsGeometry.lerp(a?.extendedPadding, b?.extendedPadding, t),
);
}
@@ -209,6 +216,7 @@
largeSizeConstraints,
extendedSizeConstraints,
extendedIconLabelSpacing,
+ extendedPadding,
);
}
@@ -235,7 +243,8 @@
&& other.smallSizeConstraints == smallSizeConstraints
&& other.largeSizeConstraints == largeSizeConstraints
&& other.extendedSizeConstraints == extendedSizeConstraints
- && other.extendedIconLabelSpacing == extendedIconLabelSpacing;
+ && other.extendedIconLabelSpacing == extendedIconLabelSpacing
+ && other.extendedPadding == extendedPadding;
}
@override
@@ -259,5 +268,6 @@
properties.add(DiagnosticsProperty<BoxConstraints>('largeSizeConstraints', largeSizeConstraints, defaultValue: null));
properties.add(DiagnosticsProperty<BoxConstraints>('extendedSizeConstraints', extendedSizeConstraints, defaultValue: null));
properties.add(DoubleProperty('extendedIconLabelSpacing', extendedIconLabelSpacing, defaultValue: null));
+ properties.add(DiagnosticsProperty<EdgeInsetsGeometry>('extendedPadding', extendedPadding, defaultValue: null));
}
}
diff --git a/packages/flutter/test/material/floating_action_button_test.dart b/packages/flutter/test/material/floating_action_button_test.dart
index a71521e..2989358 100644
--- a/packages/flutter/test/material/floating_action_button_test.dart
+++ b/packages/flutter/test/material/floating_action_button_test.dart
@@ -998,10 +998,11 @@
expect(tester.getSize(find.byKey(key)), const Size(96.0, 96.0));
});
- testWidgets('FloatingActionButton.extended can customize spacing between icon and label', (WidgetTester tester) async {
+ testWidgets('FloatingActionButton.extended can customize spacing', (WidgetTester tester) async {
const Key iconKey = Key('icon');
const Key labelKey = Key('label');
const double spacing = 33.0;
+ const EdgeInsetsDirectional padding = EdgeInsetsDirectional.only(start: 5.0, end: 6.0);
await tester.pumpWidget(
MaterialApp(
@@ -1010,6 +1011,7 @@
label: const Text('', key: labelKey),
icon: const Icon(Icons.add, key: iconKey),
extendedIconLabelSpacing: spacing,
+ extendedPadding: padding,
onPressed: () {},
),
),
@@ -1017,6 +1019,8 @@
);
expect(tester.getTopLeft(find.byKey(labelKey)).dx - tester.getTopRight(find.byKey(iconKey)).dx, spacing);
+ 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);
});
group('feedback', () {
diff --git a/packages/flutter/test/material/floating_action_button_theme_test.dart b/packages/flutter/test/material/floating_action_button_theme_test.dart
index 22a306f..e0c486c 100644
--- a/packages/flutter/test/material/floating_action_button_theme_test.dart
+++ b/packages/flutter/test/material/floating_action_button_theme_test.dart
@@ -180,13 +180,15 @@
const Key iconKey = Key('icon');
const Key labelKey = Key('label');
const BoxConstraints constraints = BoxConstraints.tightFor(height: 100.0);
- const double spacing = 33.0;
+ const double iconLabelSpacing = 33.0;
+ const EdgeInsetsDirectional padding = EdgeInsetsDirectional.only(start: 5.0, end: 6.0);
await tester.pumpWidget(MaterialApp(
theme: ThemeData().copyWith(
floatingActionButtonTheme: const FloatingActionButtonThemeData(
extendedSizeConstraints: constraints,
- extendedIconLabelSpacing: spacing,
+ extendedIconLabelSpacing: iconLabelSpacing,
+ extendedPadding: padding,
),
),
home: Scaffold(
@@ -199,18 +201,22 @@
));
expect(_getRawMaterialButton(tester).constraints, constraints);
- expect(tester.getTopLeft(find.byKey(labelKey)).dx - tester.getTopRight(find.byKey(iconKey)).dx, spacing);
+ 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.getTopRight(find.byType(FloatingActionButton)).dx - tester.getTopRight(find.byKey(labelKey)).dx, padding.end);
});
testWidgets('FloatingActionButton.extended spacing takes priority over FloatingActionButtonThemeData spacing', (WidgetTester tester) async {
const Key iconKey = Key('icon');
const Key labelKey = Key('label');
- const double spacing = 33.0;
+ const double iconLabelSpacing = 33.0;
+ const EdgeInsetsDirectional padding = EdgeInsetsDirectional.only(start: 5.0, end: 6.0);
await tester.pumpWidget(MaterialApp(
theme: ThemeData().copyWith(
floatingActionButtonTheme: const FloatingActionButtonThemeData(
extendedIconLabelSpacing: 25.0,
+ extendedPadding: EdgeInsetsDirectional.only(start: 7.0, end: 8.0),
),
),
home: Scaffold(
@@ -218,12 +224,15 @@
onPressed: () { },
label: const Text('Extended', key: labelKey),
icon: const Icon(Icons.add, key: iconKey),
- extendedIconLabelSpacing: spacing,
+ extendedIconLabelSpacing: iconLabelSpacing,
+ extendedPadding: padding,
),
),
));
- expect(tester.getTopLeft(find.byKey(labelKey)).dx - tester.getTopRight(find.byKey(iconKey)).dx, spacing);
+ 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.getTopRight(find.byType(FloatingActionButton)).dx - tester.getTopRight(find.byKey(labelKey)).dx, padding.end);
});
testWidgets('default FloatingActionButton debugFillProperties', (WidgetTester tester) async {
@@ -258,6 +267,7 @@
largeSizeConstraints: BoxConstraints.tightFor(width: 102.0, height: 102.0),
extendedSizeConstraints: BoxConstraints(minHeight: 103.0, maxHeight: 103.0),
extendedIconLabelSpacing: 12,
+ extendedPadding: EdgeInsetsDirectional.only(start: 7.0, end: 8.0),
).debugFillProperties(builder);
final List<String> description = builder.properties
@@ -282,7 +292,8 @@
'smallSizeConstraints: BoxConstraints(w=101.0, h=101.0)',
'largeSizeConstraints: BoxConstraints(w=102.0, h=102.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)',
]);
});
}