Revert "Reland: Set IconButton.visualDensity default to VisualDensity.standard (#109432)" (#110119) (#110136)
This reverts commit 79013b2be8d5e726bb4447bce665f63b5eb9308a.
Co-authored-by: Qun Cheng <36861262+QuncCccccc@users.noreply.github.com>
diff --git a/dev/tools/gen_defaults/lib/icon_button_template.dart b/dev/tools/gen_defaults/lib/icon_button_template.dart
index 10a2009..0e8a9b5 100644
--- a/dev/tools/gen_defaults/lib/icon_button_template.dart
+++ b/dev/tools/gen_defaults/lib/icon_button_template.dart
@@ -108,7 +108,7 @@
});
@override
- VisualDensity? get visualDensity => VisualDensity.standard;
+ VisualDensity? get visualDensity => Theme.of(context).visualDensity;
@override
MaterialTapTargetSize? get tapTargetSize => Theme.of(context).materialTapTargetSize;
diff --git a/examples/api/lib/material/icon_button/icon_button.3.dart b/examples/api/lib/material/icon_button/icon_button.3.dart
index 1e819a4..230d292 100644
--- a/examples/api/lib/material/icon_button/icon_button.3.dart
+++ b/examples/api/lib/material/icon_button/icon_button.3.dart
@@ -19,6 +19,10 @@
theme: ThemeData(
colorSchemeSeed: const Color(0xff6750a4),
useMaterial3: true,
+ // Desktop and web platforms have a compact visual density by default.
+ // To see buttons with circular background on desktop/web, the "visualDensity"
+ // needs to be set to "VisualDensity.standard".
+ visualDensity: VisualDensity.standard,
),
title: 'Icon Button Types',
home: const Scaffold(
diff --git a/examples/api/test/widgets/heroes/hero.0_test.dart b/examples/api/test/widgets/heroes/hero.0_test.dart
index 0cea769..058436d 100644
--- a/examples/api/test/widgets/heroes/hero.0_test.dart
+++ b/examples/api/test/widgets/heroes/hero.0_test.dart
@@ -13,32 +13,32 @@
);
expect(find.text('Hero Sample'), findsOneWidget);
- await tester.tap(find.byType(example.BoxWidget));
+ await tester.tap(find.byType(Container));
await tester.pump();
- Size heroSize = tester.getSize(find.byType(example.BoxWidget));
+ Size heroSize = tester.getSize(find.byType(Container));
// Jump 25% into the transition (total length = 300ms)
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget));
+ heroSize = tester.getSize(find.byType(Container));
expect(heroSize.width.roundToDouble(), 103.0);
expect(heroSize.height.roundToDouble(), 60.0);
// Jump to 50% into the transition.
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget));
+ heroSize = tester.getSize(find.byType(Container));
expect(heroSize.width.roundToDouble(), 189.0);
expect(heroSize.height.roundToDouble(), 146.0);
// Jump to 75% into the transition.
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget));
+ heroSize = tester.getSize(find.byType(Container));
expect(heroSize.width.roundToDouble(), 199.0);
expect(heroSize.height.roundToDouble(), 190.0);
// Jump to 100% into the transition.
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget));
+ heroSize = tester.getSize(find.byType(Container));
expect(heroSize, const Size(200.0, 200.0));
expect(find.byIcon(Icons.arrow_back), findsOneWidget);
@@ -47,25 +47,25 @@
// Jump 25% into the transition (total length = 300ms)
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget));
+ heroSize = tester.getSize(find.byType(Container));
expect(heroSize.width.roundToDouble(), 199.0);
expect(heroSize.height.roundToDouble(), 190.0);
// Jump to 50% into the transition.
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget));
+ heroSize = tester.getSize(find.byType(Container));
expect(heroSize.width.roundToDouble(), 189.0);
expect(heroSize.height.roundToDouble(), 146.0);
// Jump to 75% into the transition.
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget));
+ heroSize = tester.getSize(find.byType(Container));
expect(heroSize.width.roundToDouble(), 103.0);
expect(heroSize.height.roundToDouble(), 60.0);
// Jump to 100% into the transition.
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget));
+ heroSize = tester.getSize(find.byType(Container));
expect(heroSize, const Size(50.0, 50.0));
});
}
diff --git a/examples/api/test/widgets/heroes/hero.1_test.dart b/examples/api/test/widgets/heroes/hero.1_test.dart
index 861e23b..18cd601 100644
--- a/examples/api/test/widgets/heroes/hero.1_test.dart
+++ b/examples/api/test/widgets/heroes/hero.1_test.dart
@@ -16,30 +16,30 @@
await tester.tap(find.byType(ElevatedButton));
await tester.pump();
- Size heroSize = tester.getSize(find.byType(example.BoxWidget).first);
+ Size heroSize = tester.getSize(find.byType(Container).first);
expect(heroSize, const Size(50.0, 50.0));
// Jump 25% into the transition (total length = 300ms)
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget).first);
+ heroSize = tester.getSize(find.byType(Container).first);
expect(heroSize.width.roundToDouble(), 171.0);
expect(heroSize.height.roundToDouble(), 73.0);
// Jump to 50% into the transition.
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget).first);
+ heroSize = tester.getSize(find.byType(Container).first);
expect(heroSize.width.roundToDouble(), 371.0);
expect(heroSize.height.roundToDouble(), 273.0);
// Jump to 75% into the transition.
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget).first);
+ heroSize = tester.getSize(find.byType(Container).first);
expect(heroSize.width.roundToDouble(), 398.0);
expect(heroSize.height.roundToDouble(), 376.0);
// Jump to 100% into the transition.
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget).first);
+ heroSize = tester.getSize(find.byType(Container).first);
expect(heroSize, const Size(400.0, 400.0));
expect(find.byIcon(Icons.arrow_back), findsOneWidget);
@@ -48,25 +48,25 @@
// Jump 25% into the transition (total length = 300ms)
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget).first);
+ heroSize = tester.getSize(find.byType(Container).first);
expect(heroSize.width.roundToDouble(), 398.0);
expect(heroSize.height.roundToDouble(), 376.0);
// Jump to 50% into the transition.
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget).first);
+ heroSize = tester.getSize(find.byType(Container).first);
expect(heroSize.width.roundToDouble(), 371.0);
expect(heroSize.height.roundToDouble(), 273.0);
// Jump to 75% into the transition.
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget).first);
+ heroSize = tester.getSize(find.byType(Container).first);
expect(heroSize.width.roundToDouble(), 171.0);
expect(heroSize.height.roundToDouble(), 73.0);
// Jump to 100% into the transition.
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget).first);
+ heroSize = tester.getSize(find.byType(Container).first);
expect(heroSize, const Size(50.0, 50.0));
});
@@ -79,30 +79,30 @@
await tester.tap(find.byType(ElevatedButton));
await tester.pump();
- Size heroSize = tester.getSize(find.byType(example.BoxWidget).last);
+ Size heroSize = tester.getSize(find.byType(Container).last);
expect(heroSize, const Size(50.0, 50.0));
// Jump 25% into the transition (total length = 300ms)
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget).last);
+ heroSize = tester.getSize(find.byType(Container).last);
expect(heroSize.width.roundToDouble(), 133.0);
expect(heroSize.height.roundToDouble(), 133.0);
// Jump to 50% into the transition.
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget).last);
+ heroSize = tester.getSize(find.byType(Container).last);
expect(heroSize.width.roundToDouble(), 321.0);
expect(heroSize.height.roundToDouble(), 321.0);
// Jump to 75% into the transition.
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget).first);
+ heroSize = tester.getSize(find.byType(Container).first);
expect(heroSize.width.roundToDouble(), 398.0);
expect(heroSize.height.roundToDouble(), 376.0);
// Jump to 100% into the transition.
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget).last);
+ heroSize = tester.getSize(find.byType(Container).last);
expect(heroSize, const Size(400.0, 400.0));
expect(find.byIcon(Icons.arrow_back), findsOneWidget);
@@ -111,25 +111,25 @@
// Jump 25% into the transition (total length = 300ms)
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget).last);
+ heroSize = tester.getSize(find.byType(Container).last);
expect(heroSize.width.roundToDouble(), 386.0);
expect(heroSize.height.roundToDouble(), 386.0);
// Jump to 50% into the transition.
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget).last);
+ heroSize = tester.getSize(find.byType(Container).last);
expect(heroSize.width.roundToDouble(), 321.0);
expect(heroSize.height.roundToDouble(), 321.0);
// Jump to 75% into the transition.
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget).last);
+ heroSize = tester.getSize(find.byType(Container).last);
expect(heroSize.width.roundToDouble(), 133.0);
expect(heroSize.height.roundToDouble(), 133.0);
// Jump to 100% into the transition.
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
- heroSize = tester.getSize(find.byType(example.BoxWidget).last);
+ heroSize = tester.getSize(find.byType(Container).last);
expect(heroSize, const Size(50.0, 50.0));
});
}
diff --git a/packages/flutter/lib/src/material/app_bar.dart b/packages/flutter/lib/src/material/app_bar.dart
index b690185..e031d93 100644
--- a/packages/flutter/lib/src/material/app_bar.dart
+++ b/packages/flutter/lib/src/material/app_bar.dart
@@ -998,8 +998,7 @@
}
}
if (leading != null) {
- leading = Container(
- alignment: Alignment.center,
+ leading = ConstrainedBox(
constraints: BoxConstraints.tightFor(width: widget.leadingWidth ?? _kLeadingWidth),
child: leading,
);
@@ -1057,7 +1056,7 @@
if (widget.actions != null && widget.actions!.isNotEmpty) {
actions = Row(
mainAxisSize: MainAxisSize.min,
- crossAxisAlignment: theme.useMaterial3 ? CrossAxisAlignment.center : CrossAxisAlignment.stretch,
+ crossAxisAlignment: CrossAxisAlignment.stretch,
children: widget.actions!,
);
} else if (hasEndDrawer) {
diff --git a/packages/flutter/lib/src/material/icon_button.dart b/packages/flutter/lib/src/material/icon_button.dart
index 3c47720..a1c8cbd 100644
--- a/packages/flutter/lib/src/material/icon_button.dart
+++ b/packages/flutter/lib/src/material/icon_button.dart
@@ -132,11 +132,6 @@
/// precedence: widget property, [IconButtonTheme] property, [IconTheme] property and
/// internal default property value.
///
-/// In Material Design 3, the [IconButton.visualDensity] defaults to [VisualDensity.standard]
-/// for all platforms because the button will have a rounded rectangle shape if
-/// the [IconButton.visualDensity] is set to [VisualDensity.compact]. Users can
-/// customize it by using [IconButtonTheme], [IconButton.style] or [IconButton.visualDensity].
-///
/// {@tool dartpad}
/// This sample shows creation of [IconButton] widgets for standard, filled,
/// filled tonal and outlined types, as described in: https://m3.material.io/components/icon-buttons/overview
@@ -223,9 +218,6 @@
///
/// {@macro flutter.material.themedata.visualDensity}
///
- /// This property can be null. If null, it defaults to [VisualDensity.standard]
- /// in Material Design 3 to make sure the button will be circular on all platforms.
- ///
/// See also:
///
/// * [ThemeData.visualDensity], which specifies the [visualDensity] for all
@@ -819,7 +811,7 @@
/// * `mouseCursor`
/// * disabled - SystemMouseCursors.basic
/// * others - SystemMouseCursors.click
- /// * `visualDensity` - VisualDensity.standard
+ /// * `visualDensity` - theme.visualDensity
/// * `tapTargetSize` - theme.materialTapTargetSize
/// * `animationDuration` - kThemeChangeDuration
/// * `enableFeedback` - true
@@ -1061,7 +1053,7 @@
});
@override
- VisualDensity? get visualDensity => VisualDensity.standard;
+ VisualDensity? get visualDensity => Theme.of(context).visualDensity;
@override
MaterialTapTargetSize? get tapTargetSize => Theme.of(context).materialTapTargetSize;
diff --git a/packages/flutter/lib/src/material/theme_data.dart b/packages/flutter/lib/src/material/theme_data.dart
index b92f569..c7c0c75 100644
--- a/packages/flutter/lib/src/material/theme_data.dart
+++ b/packages/flutter/lib/src/material/theme_data.dart
@@ -1261,11 +1261,6 @@
///
/// A larger value translates to a spacing increase (less dense), and a
/// smaller value translates to a spacing decrease (more dense).
- ///
- /// In Material Design 3, the [visualDensity] does not override the value of
- /// [IconButton.visualDensity] which defaults to [VisualDensity.standard]
- /// for all platforms. To override the default value of [IconButton.visualDensity],
- /// use [ThemeData.iconButtonTheme] instead.
/// {@endtemplate}
final VisualDensity visualDensity;
diff --git a/packages/flutter/test/material/app_bar_test.dart b/packages/flutter/test/material/app_bar_test.dart
index aec7e26..acf54c2 100644
--- a/packages/flutter/test/material/app_bar_test.dart
+++ b/packages/flutter/test/material/app_bar_test.dart
@@ -707,8 +707,8 @@
);
final Finder hamburger = find.byTooltip('Open navigation menu');
- expect(tester.getTopLeft(hamburger), const Offset(4.0, 4.0));
- expect(tester.getSize(hamburger), const Size(48.0, 48.0));
+ expect(tester.getTopLeft(hamburger), Offset.zero);
+ expect(tester.getSize(hamburger), const Size(56.0, 56.0));
});
testWidgets('test action is 4dp from edge and 48dp min', (WidgetTester tester) async {
@@ -737,12 +737,12 @@
),
);
- final Finder addButton = find.widgetWithIcon(IconButton, Icons.add);
+ final Finder addButton = find.byTooltip('Add');
expect(tester.getTopRight(addButton), const Offset(800.0, 0.0));
// It's still the size it was plus the 2 * 8dp padding from IconButton.
expect(tester.getSize(addButton), const Size(60.0 + 2 * 8.0, 56.0));
- final Finder shareButton = find.widgetWithIcon(IconButton, Icons.share);
+ final Finder shareButton = find.byTooltip('Share');
// The 20dp icon is expanded to fill the IconButton's touch target to 48dp.
expect(tester.getSize(shareButton), const Size(48.0, 56.0));
});
diff --git a/packages/flutter/test/material/icon_button_test.dart b/packages/flutter/test/material/icon_button_test.dart
index 9eeb689..271db0f 100644
--- a/packages/flutter/test/material/icon_button_test.dart
+++ b/packages/flutter/test/material/icon_button_test.dart
@@ -275,23 +275,11 @@
testWidgets('Small icons comply with VisualDensity requirements', (WidgetTester tester) async {
final bool material3 = theme.useMaterial3;
- final ThemeData themeDataM2 = ThemeData(
- useMaterial3: material3,
- visualDensity: const VisualDensity(horizontal: 1, vertical: -1),
- );
- final ThemeData themeDataM3 = ThemeData(
- useMaterial3: material3,
- iconButtonTheme: IconButtonThemeData(
- style: IconButton.styleFrom(
- visualDensity: const VisualDensity(horizontal: 1, vertical: -1)
- )
- ),
- );
await tester.pumpWidget(
wrap(
useMaterial3: material3,
child: Theme(
- data: material3 ? themeDataM3 : themeDataM2,
+ data: ThemeData(visualDensity: const VisualDensity(horizontal: 1, vertical: -1), useMaterial3: material3),
child: IconButton(
iconSize: 10.0,
onPressed: mockOnPressedFunction.handler,
@@ -447,7 +435,6 @@
});
testWidgets('IconButton AppBar size', (WidgetTester tester) async {
- final bool material3 = theme.useMaterial3;
await tester.pumpWidget(
MaterialApp(
theme: theme,
@@ -467,8 +454,7 @@
final RenderBox barBox = tester.renderObject(find.byType(AppBar));
final RenderBox iconBox = tester.renderObject(find.byType(IconButton));
- expect(iconBox.size.height, material3 ? 48 : equals(barBox.size.height));
- expect(tester.getCenter(find.byType(IconButton)).dy, 28);
+ expect(iconBox.size.height, equals(barBox.size.height));
});
// This test is very similar to the '...explicit splashColor and highlightColor' test
@@ -1643,56 +1629,6 @@
expect(find.byIcon(Icons.ac_unit), findsOneWidget);
});
- testWidgets('The visualDensity of M3 IconButton can be configured by IconButtonTheme, '
- 'but cannot be configured by ThemeData - M3' , (WidgetTester tester) async {
- Future<void> buildTest({VisualDensity? iconButtonThemeVisualDensity, VisualDensity? themeVisualDensity}) async {
- return tester.pumpWidget(
- MaterialApp(
- theme: ThemeData.from(colorScheme: colorScheme, useMaterial3: true).copyWith(
- iconButtonTheme: IconButtonThemeData(
- style: IconButton.styleFrom(visualDensity: iconButtonThemeVisualDensity)
- ),
- visualDensity: themeVisualDensity
- ),
- home: Material(
- child: Center(
- child: IconButton(
- onPressed: () {},
- icon: const Icon(Icons.play_arrow),
- ),
- ),
- ),
- ),
- );
- }
-
- await buildTest(iconButtonThemeVisualDensity: VisualDensity.standard);
- final RenderBox box = tester.renderObject(find.byType(IconButton));
- await tester.pumpAndSettle();
- expect(box.size, equals(const Size(48, 48)));
-
- await buildTest(iconButtonThemeVisualDensity: VisualDensity.compact);
- await tester.pumpAndSettle();
- expect(box.size, equals(const Size(40, 40)));
-
- await buildTest(iconButtonThemeVisualDensity: const VisualDensity(horizontal: 3.0, vertical: 3.0));
- await tester.pumpAndSettle();
- expect(box.size, equals(const Size(64, 64)));
-
- // ThemeData.visualDensity will be ignored because useMaterial3 is true
- await buildTest(themeVisualDensity: VisualDensity.standard);
- await tester.pumpAndSettle();
- expect(box.size, equals(const Size(48, 48)));
-
- await buildTest(themeVisualDensity: VisualDensity.compact);
- await tester.pumpAndSettle();
- expect(box.size, equals(const Size(48, 48)));
-
- await buildTest(themeVisualDensity: const VisualDensity(horizontal: 3.0, vertical: 3.0));
- await tester.pumpAndSettle();
- expect(box.size, equals(const Size(48, 48)));
- });
-
group('IconTheme tests in Material 3', () {
testWidgets('IconTheme overrides default values in M3', (WidgetTester tester) async {
// Theme's IconTheme