mirror of
https://github.com/flutter/flutter
synced 2024-10-13 03:32:55 +00:00
Allow for customizing and theming of extended FAB content padding (#87062)
This commit is contained in:
parent
738ce43d97
commit
83a215ed09
|
@ -171,6 +171,7 @@ class FloatingActionButton extends StatelessWidget {
|
|||
_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 @@ class FloatingActionButton extends StatelessWidget {
|
|||
isExtended = false,
|
||||
_extendedLabel = null,
|
||||
extendedIconLabelSpacing = null,
|
||||
extendedPadding = null,
|
||||
super(key: key);
|
||||
|
||||
/// Creates a large circular floating action button.
|
||||
|
@ -263,6 +265,7 @@ class FloatingActionButton extends StatelessWidget {
|
|||
isExtended = false,
|
||||
_extendedLabel = null,
|
||||
extendedIconLabelSpacing = null,
|
||||
extendedPadding = null,
|
||||
super(key: key);
|
||||
|
||||
/// Creates a wider [StadiumBorder]-shaped floating action button with
|
||||
|
@ -294,6 +297,7 @@ class FloatingActionButton extends StatelessWidget {
|
|||
this.focusNode,
|
||||
this.autofocus = false,
|
||||
this.extendedIconLabelSpacing,
|
||||
this.extendedPadding,
|
||||
Widget? icon,
|
||||
required Widget label,
|
||||
this.enableFeedback,
|
||||
|
@ -518,6 +522,14 @@ class FloatingActionButton extends StatelessWidget {
|
|||
/// 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 @@ class FloatingActionButton extends StatelessWidget {
|
|||
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;
|
||||
|
|
|
@ -48,6 +48,7 @@ class FloatingActionButtonThemeData with Diagnosticable {
|
|||
this.largeSizeConstraints,
|
||||
this.extendedSizeConstraints,
|
||||
this.extendedIconLabelSpacing,
|
||||
this.extendedPadding,
|
||||
});
|
||||
|
||||
/// Color to be used for the unselected, enabled [FloatingActionButton]'s
|
||||
|
@ -117,6 +118,9 @@ class FloatingActionButtonThemeData with Diagnosticable {
|
|||
/// [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 @@ class FloatingActionButtonThemeData with Diagnosticable {
|
|||
BoxConstraints? largeSizeConstraints,
|
||||
BoxConstraints? extendedSizeConstraints,
|
||||
double? extendedIconLabelSpacing,
|
||||
EdgeInsetsGeometry? extendedPadding,
|
||||
}) {
|
||||
return FloatingActionButtonThemeData(
|
||||
foregroundColor: foregroundColor ?? this.foregroundColor,
|
||||
|
@ -156,6 +161,7 @@ class FloatingActionButtonThemeData with Diagnosticable {
|
|||
largeSizeConstraints: largeSizeConstraints ?? this.largeSizeConstraints,
|
||||
extendedSizeConstraints: extendedSizeConstraints ?? this.extendedSizeConstraints,
|
||||
extendedIconLabelSpacing: extendedIconLabelSpacing ?? this.extendedIconLabelSpacing,
|
||||
extendedPadding: extendedPadding ?? this.extendedPadding,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -186,6 +192,7 @@ class FloatingActionButtonThemeData with Diagnosticable {
|
|||
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 @@ class FloatingActionButtonThemeData with Diagnosticable {
|
|||
largeSizeConstraints,
|
||||
extendedSizeConstraints,
|
||||
extendedIconLabelSpacing,
|
||||
extendedPadding,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -235,7 +243,8 @@ class FloatingActionButtonThemeData with Diagnosticable {
|
|||
&& other.smallSizeConstraints == smallSizeConstraints
|
||||
&& other.largeSizeConstraints == largeSizeConstraints
|
||||
&& other.extendedSizeConstraints == extendedSizeConstraints
|
||||
&& other.extendedIconLabelSpacing == extendedIconLabelSpacing;
|
||||
&& other.extendedIconLabelSpacing == extendedIconLabelSpacing
|
||||
&& other.extendedPadding == extendedPadding;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -259,5 +268,6 @@ class FloatingActionButtonThemeData with Diagnosticable {
|
|||
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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -998,10 +998,11 @@ void main() {
|
|||
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 @@ void main() {
|
|||
label: const Text('', key: labelKey),
|
||||
icon: const Icon(Icons.add, key: iconKey),
|
||||
extendedIconLabelSpacing: spacing,
|
||||
extendedPadding: padding,
|
||||
onPressed: () {},
|
||||
),
|
||||
),
|
||||
|
@ -1017,6 +1019,8 @@ void main() {
|
|||
);
|
||||
|
||||
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', () {
|
||||
|
|
|
@ -180,13 +180,15 @@ void main() {
|
|||
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 @@ void main() {
|
|||
));
|
||||
|
||||
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 @@ void main() {
|
|||
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 @@ void main() {
|
|||
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 @@ void main() {
|
|||
'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)',
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue