diff --git a/packages/flutter/lib/src/material/banner.dart b/packages/flutter/lib/src/material/banner.dart index fdbc6c9a0d..ab6babd1d6 100644 --- a/packages/flutter/lib/src/material/banner.dart +++ b/packages/flutter/lib/src/material/banner.dart @@ -7,8 +7,6 @@ import 'package:flutter/widgets.dart'; import 'banner_theme.dart'; -import 'button_bar.dart'; -import 'button_theme.dart'; import 'divider.dart'; import 'theme.dart'; @@ -66,9 +64,6 @@ class MaterialBanner extends StatelessWidget { /// the [MaterialBanner]. /// /// Typically this is a list of [TextButton] widgets. - /// - /// These widgets will be wrapped in a [ButtonBar], which introduces 8 pixels - /// of padding on each side. final List actions; /// The (optional) leading widget of the [MaterialBanner]. @@ -120,9 +115,14 @@ class MaterialBanner extends StatelessWidget { ?? bannerTheme.leadingPadding ?? const EdgeInsetsDirectional.only(end: 16.0); - final Widget buttonBar = ButtonBar( - layoutBehavior: ButtonBarLayoutBehavior.constrained, - children: actions, + final Widget buttonBar = Container( + alignment: AlignmentDirectional.centerEnd, + constraints: const BoxConstraints(minHeight: 52.0), + padding: const EdgeInsets.symmetric(horizontal: 8), + child: OverflowBar( + spacing: 8, + children: actions, + ), ); final Color backgroundColor = this.backgroundColor diff --git a/packages/flutter/test/material/banner_test.dart b/packages/flutter/test/material/banner_test.dart index 9a65246653..52db15a2f9 100644 --- a/packages/flutter/test/material/banner_test.dart +++ b/packages/flutter/test/material/banner_test.dart @@ -74,9 +74,9 @@ void main() { ); final Offset contentBottomLeft = tester.getBottomLeft(find.text(contentText)); - final Offset actionsTopRight = tester.getTopLeft(find.byType(ButtonBar)); - expect(contentBottomLeft.dy, lessThan(actionsTopRight.dy)); - expect(contentBottomLeft.dx, greaterThan(actionsTopRight.dx)); + final Offset actionsTopLeft = tester.getTopLeft(find.byType(OverflowBar)); + expect(contentBottomLeft.dy, lessThan(actionsTopLeft.dy)); + expect(contentBottomLeft.dx, lessThan(actionsTopLeft.dx)); }); testWidgets('Actions laid out beside content if only one action', (WidgetTester tester) async { @@ -97,7 +97,7 @@ void main() { ); final Offset contentBottomLeft = tester.getBottomLeft(find.text(contentText)); - final Offset actionsTopRight = tester.getTopRight(find.byType(ButtonBar)); + final Offset actionsTopRight = tester.getTopRight(find.byType(OverflowBar)); expect(contentBottomLeft.dy, greaterThan(actionsTopRight.dy)); expect(contentBottomLeft.dx, lessThan(actionsTopRight.dx)); }); @@ -118,9 +118,9 @@ void main() { ), ); - final Offset actionsTopRight = tester.getTopRight(find.byType(ButtonBar)); + final Offset actionsTopRight = tester.getTopRight(find.byType(OverflowBar)); final Offset bannerTopRight = tester.getTopRight(find.byType(MaterialBanner)); - expect(actionsTopRight.dx, bannerTopRight.dx); + expect(actionsTopRight.dx + 8, bannerTopRight.dx); // actions OverflowBar is padded by 8 }); // Regression test for https://github.com/flutter/flutter/issues/39574 @@ -142,9 +142,9 @@ void main() { ), ); - final Offset actionsTopLeft = tester.getTopLeft(find.byType(ButtonBar)); + final Offset actionsTopLeft = tester.getTopLeft(find.byType(OverflowBar)); final Offset bannerTopLeft = tester.getTopLeft(find.byType(MaterialBanner)); - expect(actionsTopLeft.dx, bannerTopLeft.dx); + expect(actionsTopLeft.dx - 8, bannerTopLeft.dx); // actions OverflowBar is padded by 8 }); testWidgets('Actions laid out below content if forced override', (WidgetTester tester) async { @@ -166,9 +166,92 @@ void main() { ); final Offset contentBottomLeft = tester.getBottomLeft(find.text(contentText)); - final Offset actionsTopRight = tester.getTopLeft(find.byType(ButtonBar)); - expect(contentBottomLeft.dy, lessThan(actionsTopRight.dy)); - expect(contentBottomLeft.dx, greaterThan(actionsTopRight.dx)); + final Offset actionsTopLeft = tester.getTopLeft(find.byType(OverflowBar)); + expect(contentBottomLeft.dy, lessThan(actionsTopLeft.dy)); + expect(contentBottomLeft.dx, lessThan(actionsTopLeft.dx)); + }); + + testWidgets('Action widgets layout', (WidgetTester tester) async { + // This regression test ensures that the action widgets layout matches what + // it was, before ButtonBar was replaced by OverflowBar. + + Widget buildFrame(int actionCount, TextDirection textDirection) { + return MaterialApp( + home: Directionality( + textDirection: textDirection, + child: MaterialBanner( + content: const SizedBox(width: 100, height: 100), + actions: List.generate(actionCount, (int index) { + return SizedBox( + width: 64, + height: 48, + key: ValueKey(index), + ); + }), + ), + ), + ); + } + + final Finder action0 = find.byKey(const ValueKey(0)); + final Finder action1 = find.byKey(const ValueKey(1)); + final Finder action2 = find.byKey(const ValueKey(2)); + + // The action coordinates that follow were obtained by running + // the test code, before ButtonBar was replaced by OverflowBar. + + await tester.pumpWidget(buildFrame(1, TextDirection.ltr)); + expect(tester.getTopLeft(action0), const Offset(728, 28)); + + await tester.pumpWidget(buildFrame(1, TextDirection.rtl)); + expect(tester.getTopLeft(action0), const Offset(8, 28)); + + await tester.pumpWidget(buildFrame(3, TextDirection.ltr)); + expect(tester.getTopLeft(action0), const Offset(584, 130)); + expect(tester.getTopLeft(action1), const Offset(656, 130)); + expect(tester.getTopLeft(action2), const Offset(728, 130)); + + await tester.pumpWidget(buildFrame(3, TextDirection.rtl)); + expect(tester.getTopLeft(action0), const Offset(152, 130)); + expect(tester.getTopLeft(action1), const Offset(80, 130)); + expect(tester.getTopLeft(action2), const Offset(8, 130)); + }); + + testWidgets('Action widgets layout with overflow', (WidgetTester tester) async { + // This regression test ensures that the action widgets layout matches what + // it was, before ButtonBar was replaced by OverflowBar. + + const int actionCount = 4; + Widget buildFrame(TextDirection textDirection) { + return MaterialApp( + home: Directionality( + textDirection: textDirection, + child: MaterialBanner( + content: const SizedBox(width: 100, height: 100), + actions: List.generate(actionCount, (int index) { + return SizedBox( + width: 200, + height: 10, + key: ValueKey(index), + ); + }), + ), + ), + ); + } + + // The action coordinates that follow were obtained by running + // the test code, before ButtonBar was replaced by OverflowBar. + + await tester.pumpWidget(buildFrame(TextDirection.ltr)); + for (int index = 0; index < actionCount; index += 1) { + expect(tester.getTopLeft(find.byKey(ValueKey(index))), Offset(8, 134.0 + index * 10)); + } + + await tester.pumpWidget(buildFrame(TextDirection.rtl)); + for (int index = 0; index < actionCount; index += 1) { + expect(tester.getTopLeft(find.byKey(ValueKey(index))), Offset(592, 134.0 + index * 10)); + } }); }