diff --git a/packages/flutter/lib/src/material/floating_action_button.dart b/packages/flutter/lib/src/material/floating_action_button.dart index 9f820a9ad9..9d4e8de530 100644 --- a/packages/flutter/lib/src/material/floating_action_button.dart +++ b/packages/flutter/lib/src/material/floating_action_button.dart @@ -92,10 +92,10 @@ class FloatingActionButton extends StatelessWidget { disabledElevation = disabledElevation ?? elevation, super(key: key); - /// Creates a wider [StadiumBorder]-shaped floating action button with both - /// an [icon] and a [label]. + /// Creates a wider [StadiumBorder]-shaped floating action button with + /// an optional [icon] and a [label]. /// - /// The [label], [icon], [elevation], [highlightElevation], [clipBehavior] and + /// The [label], [elevation], [highlightElevation], [clipBehavior] and /// [shape] arguments must not be null. Additionally, [elevation] /// [highlightElevation], and [disabledElevation] (if specified) must be /// non-negative. @@ -113,7 +113,7 @@ class FloatingActionButton extends StatelessWidget { this.isExtended = true, this.materialTapTargetSize, this.clipBehavior = Clip.none, - @required Widget icon, + Widget icon, @required Widget label, }) : assert(elevation != null && elevation >= 0.0), assert(highlightElevation != null && highlightElevation >= 0.0), @@ -127,13 +127,19 @@ class FloatingActionButton extends StatelessWidget { child = _ChildOverflowBox( child: Row( mainAxisSize: MainAxisSize.min, - children: [ - const SizedBox(width: 16.0), - icon, - const SizedBox(width: 8.0), - label, - const SizedBox(width: 20.0), - ], + children: icon == null + ? [ + const SizedBox(width: 20.0), + label, + const SizedBox(width: 20.0), + ] + : [ + const SizedBox(width: 16.0), + icon, + const SizedBox(width: 8.0), + label, + const SizedBox(width: 20.0), + ], ), ), super(key: key); diff --git a/packages/flutter/test/material/floating_action_button_test.dart b/packages/flutter/test/material/floating_action_button_test.dart index ef70bfc367..64a5a677b4 100644 --- a/packages/flutter/test/material/floating_action_button_test.dart +++ b/packages/flutter/test/material/floating_action_button_test.dart @@ -338,6 +338,49 @@ void main() { expect(tester.getSize(fabFinder).width, 168); }); + testWidgets('FloatingActionButton.isExtended (without icon)', (WidgetTester tester) async { + final Finder fabFinder = find.byType(FloatingActionButton); + + FloatingActionButton getFabWidget() { + return tester.widget(fabFinder); + } + + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + floatingActionButton: FloatingActionButton.extended( + label: const SizedBox( + width: 100.0, + child: Text('label'), + ), + onPressed: null, + ), + ), + ), + ); + + expect(getFabWidget().isExtended, true); + expect(getFabWidget().shape, const StadiumBorder()); + expect(find.text('label'), findsOneWidget); + expect(find.byType(Icon), findsNothing); + + // Verify that the widget's height is 48 and that its internal + /// horizontal layout is: 20 label 20 + expect(tester.getSize(fabFinder).height, 48.0); + + final double fabLeft = tester.getTopLeft(fabFinder).dx; + final double fabRight = tester.getTopRight(fabFinder).dx; + final double labelLeft = tester.getTopLeft(find.text('label')).dx; + final double labelRight = tester.getTopRight(find.text('label')).dx; + expect(labelLeft - fabLeft, 20.0); + expect(fabRight - labelRight, 20.0); + + // The overall width of the button is: + // 140 = 20 + 100(label) + 20 + expect(tester.getSize(find.text('label')).width, 100.0); + expect(tester.getSize(fabFinder).width, 140); + }); + testWidgets('Floating Action Button heroTag', (WidgetTester tester) async { BuildContext theContext; await tester.pumpWidget(