Unverified Commit f7b00234 authored by Qun Cheng's avatar Qun Cheng Committed by GitHub

Added `IconButtonTheme` and apply it to `IconButton` in M3 (#108332)

* Created IconButtonTheme and apply it to IconButton
parent 7e8f0e57
......@@ -88,6 +88,10 @@ class _${blockName}DefaultsM3 extends ButtonStyle {
MaterialStateProperty<Size>? get maximumSize =>
ButtonStyleButton.allOrNull<Size>(Size.infinite);
@override
MaterialStateProperty<double>? get iconSize =>
ButtonStyleButton.allOrNull<double>(${tokens["md.comp.icon-button.icon.size"]});
// No default side
@override
......
......@@ -89,6 +89,7 @@ export 'src/material/flutter_logo.dart';
export 'src/material/grid_tile.dart';
export 'src/material/grid_tile_bar.dart';
export 'src/material/icon_button.dart';
export 'src/material/icon_button_theme.dart';
export 'src/material/icons.dart';
export 'src/material/ink_decoration.dart';
export 'src/material/ink_highlight.dart';
......
......@@ -4,6 +4,8 @@
import 'package:flutter/painting.dart';
import 'colors.dart';
/// The minimum dimension of any interactive region according to Material
/// guidelines.
///
......@@ -47,3 +49,13 @@ const EdgeInsets kTabLabelPadding = EdgeInsets.symmetric(horizontal: 16.0);
/// The padding added around material list items.
const EdgeInsets kMaterialListPadding = EdgeInsets.symmetric(vertical: 8.0);
/// The default color for [ThemeData.iconTheme] when [ThemeData.brightness] is
/// [Brightness.light]. This color is used in [IconButton] to detect whether
/// [IconTheme.of(context).color] is the same as the default color of [ThemeData.iconTheme].
const Color kDefaultIconLightColor = Colors.white;
/// The default color for [ThemeData.iconTheme] when [ThemeData.brightness] is
/// [Brightness.dark]. This color is used in [IconButton] to detect whether
/// [IconTheme.of(context).color] is the same as the default color of [ThemeData.iconTheme].
const Color kDefaultIconDarkColor = Colors.black87;
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'button_style.dart';
import 'theme.dart';
/// A [ButtonStyle] that overrides the default appearance of
/// [IconButton]s when it's used with the [IconButton], the [IconButtonTheme] or the
/// overall [Theme]'s [ThemeData.iconButtonTheme].
///
/// The [IconButton] will be affected by [IconButtonTheme] and [IconButtonThemeData]
/// only if [ThemeData.useMaterial3] is set to true; otherwise, [IconTheme] will be used.
///
/// The [style]'s properties override [IconButton]'s default style. Only
/// the style's non-null property values or resolved non-null
/// [MaterialStateProperty] values are used.
///
/// See also:
///
/// * [IconButtonTheme], the theme which is configured with this class.
/// * [IconButton.styleFrom], which converts simple values into a
/// [ButtonStyle] that's consistent with [IconButton]'s defaults.
/// * [MaterialStateProperty.resolve], "resolve" a material state property
/// to a simple value based on a set of [MaterialState]s.
/// * [ThemeData.iconButtonTheme], which can be used to override the default
/// [ButtonStyle] for [IconButton]s below the overall [Theme].
@immutable
class IconButtonThemeData with Diagnosticable {
/// Creates a [IconButtonThemeData].
///
/// The [style] may be null.
const IconButtonThemeData({ this.style });
/// Overrides for [IconButton]'s default style if [ThemeData.useMaterial3]
/// is set to true.
///
/// Non-null properties or non-null resolved [MaterialStateProperty]
/// values override the default [ButtonStyle] in [IconButton].
///
/// If [style] is null, then this theme doesn't override anything.
final ButtonStyle? style;
/// Linearly interpolate between two icon button themes.
static IconButtonThemeData? lerp(IconButtonThemeData? a, IconButtonThemeData? b, double t) {
assert (t != null);
if (a == null && b == null) {
return null;
}
return IconButtonThemeData(
style: ButtonStyle.lerp(a?.style, b?.style, t),
);
}
@override
int get hashCode => style.hashCode;
@override
bool operator ==(Object other) {
if (identical(this, other)) {
return true;
}
if (other.runtimeType != runtimeType) {
return false;
}
return other is IconButtonThemeData && other.style == style;
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<ButtonStyle>('style', style, defaultValue: null));
}
}
/// Overrides the default [ButtonStyle] of its [IconButton] descendants.
///
/// See also:
///
/// * [IconButtonThemeData], which is used to configure this theme.
/// * [IconButton.styleFrom], which converts simple values into a
/// [ButtonStyle] that's consistent with [IconButton]'s defaults.
/// * [ThemeData.iconButtonTheme], which can be used to override the default
/// [ButtonStyle] for [IconButton]s below the overall [Theme].
class IconButtonTheme extends InheritedTheme {
/// Create a [IconButtonTheme].
///
/// The [data] parameter must not be null.
const IconButtonTheme({
super.key,
required this.data,
required super.child,
}) : assert(data != null);
/// The configuration of this theme.
final IconButtonThemeData data;
/// The closest instance of this class that encloses the given context.
///
/// If there is no enclosing [IconButtonTheme] widget, then
/// [ThemeData.iconButtonTheme] is used.
///
/// Typical usage is as follows:
///
/// ```dart
/// IconButtonThemeData theme = IconButtonTheme.of(context);
/// ```
static IconButtonThemeData of(BuildContext context) {
final IconButtonTheme? buttonTheme = context.dependOnInheritedWidgetOfExactType<IconButtonTheme>();
return buttonTheme?.data ?? Theme.of(context).iconButtonTheme;
}
@override
Widget wrap(BuildContext context, Widget child) {
return IconButtonTheme(data: data, child: child);
}
@override
bool updateShouldNotify(IconButtonTheme oldWidget) => data != oldWidget.data;
}
......@@ -37,7 +37,6 @@ const double _kMenuMinWidth = 2.0 * _kMenuWidthStep;
const double _kMenuVerticalPadding = 8.0;
const double _kMenuWidthStep = 56.0;
const double _kMenuScreenPadding = 8.0;
const double _kDefaultIconSize = 24.0;
/// Used to configure how the [PopupMenuButton] positions its popup menu.
enum PopupMenuPosition {
......@@ -1241,7 +1240,6 @@ class PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
@override
Widget build(BuildContext context) {
final IconThemeData iconTheme = IconTheme.of(context);
final bool enableFeedback = widget.enableFeedback
?? PopupMenuTheme.of(context).enableFeedback
?? true;
......@@ -1265,7 +1263,7 @@ class PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
icon: widget.icon ?? Icon(Icons.adaptive.more),
padding: widget.padding,
splashRadius: widget.splashRadius,
iconSize: widget.iconSize ?? iconTheme.size ?? _kDefaultIconSize,
iconSize: widget.iconSize,
tooltip: widget.tooltip ?? MaterialLocalizations.of(context).showMenuTooltip,
onPressed: widget.enabled ? showButtonMenu : null,
enableFeedback: enableFeedback,
......
......@@ -19,6 +19,7 @@ import 'checkbox_theme.dart';
import 'chip_theme.dart';
import 'color_scheme.dart';
import 'colors.dart';
import 'constants.dart';
import 'data_table_theme.dart';
import 'dialog_theme.dart';
import 'divider_theme.dart';
......@@ -26,6 +27,7 @@ import 'drawer_theme.dart';
import 'elevated_button_theme.dart';
import 'expansion_tile_theme.dart';
import 'floating_action_button_theme.dart';
import 'icon_button_theme.dart';
import 'ink_ripple.dart';
import 'ink_sparkle.dart';
import 'ink_splash.dart';
......@@ -114,6 +116,7 @@ const Color _kDarkThemeSplashColor = Color(0x40CCCCCC);
/// * [OutlinedButton]
/// * [TextButton]
/// * [ElevatedButton]
/// * [IconButton]
/// * The time picker widget ([showTimePicker])
/// * [SnackBar]
/// * [Chip]
......@@ -339,6 +342,7 @@ class ThemeData with Diagnosticable {
ElevatedButtonThemeData? elevatedButtonTheme,
ExpansionTileThemeData? expansionTileTheme,
FloatingActionButtonThemeData? floatingActionButtonTheme,
IconButtonThemeData? iconButtonTheme,
ListTileThemeData? listTileTheme,
NavigationBarThemeData? navigationBarTheme,
NavigationRailThemeData? navigationRailTheme,
......@@ -535,7 +539,7 @@ class ThemeData with Diagnosticable {
}
textTheme = defaultTextTheme.merge(textTheme);
primaryTextTheme = defaultPrimaryTextTheme.merge(primaryTextTheme);
iconTheme ??= isDark ? const IconThemeData(color: Colors.white) : const IconThemeData(color: Colors.black87);
iconTheme ??= isDark ? const IconThemeData(color: kDefaultIconLightColor) : const IconThemeData(color: kDefaultIconDarkColor);
primaryIconTheme ??= primaryIsDark ? const IconThemeData(color: Colors.white) : const IconThemeData(color: Colors.black);
// COMPONENT THEMES
......@@ -554,6 +558,7 @@ class ThemeData with Diagnosticable {
drawerTheme ??= const DrawerThemeData();
elevatedButtonTheme ??= const ElevatedButtonThemeData();
floatingActionButtonTheme ??= const FloatingActionButtonThemeData();
iconButtonTheme ??= const IconButtonThemeData();
listTileTheme ??= const ListTileThemeData();
navigationBarTheme ??= const NavigationBarThemeData();
navigationRailTheme ??= const NavigationRailThemeData();
......@@ -645,6 +650,7 @@ class ThemeData with Diagnosticable {
elevatedButtonTheme: elevatedButtonTheme,
expansionTileTheme: expansionTileTheme,
floatingActionButtonTheme: floatingActionButtonTheme,
iconButtonTheme: iconButtonTheme,
listTileTheme: listTileTheme,
navigationBarTheme: navigationBarTheme,
navigationRailTheme: navigationRailTheme,
......@@ -750,6 +756,7 @@ class ThemeData with Diagnosticable {
required this.elevatedButtonTheme,
required this.expansionTileTheme,
required this.floatingActionButtonTheme,
required this.iconButtonTheme,
required this.listTileTheme,
required this.navigationBarTheme,
required this.navigationRailTheme,
......@@ -892,6 +899,7 @@ class ThemeData with Diagnosticable {
assert(elevatedButtonTheme != null),
assert(expansionTileTheme != null),
assert(floatingActionButtonTheme != null),
assert(iconButtonTheme != null),
assert(listTileTheme != null),
assert(navigationBarTheme != null),
assert(navigationRailTheme != null),
......@@ -1444,6 +1452,10 @@ class ThemeData with Diagnosticable {
/// [FloatingActionButton].
final FloatingActionButtonThemeData floatingActionButtonTheme;
/// A theme for customizing the appearance and internal layout of
/// [IconButton]s.
final IconButtonThemeData iconButtonTheme;
/// A theme for customizing the appearance of [ListTile] widgets.
final ListTileThemeData listTileTheme;
......@@ -1712,6 +1724,7 @@ class ThemeData with Diagnosticable {
ElevatedButtonThemeData? elevatedButtonTheme,
ExpansionTileThemeData? expansionTileTheme,
FloatingActionButtonThemeData? floatingActionButtonTheme,
IconButtonThemeData? iconButtonTheme,
ListTileThemeData? listTileTheme,
NavigationBarThemeData? navigationBarTheme,
NavigationRailThemeData? navigationRailTheme,
......@@ -1852,6 +1865,7 @@ class ThemeData with Diagnosticable {
elevatedButtonTheme: elevatedButtonTheme ?? this.elevatedButtonTheme,
expansionTileTheme: expansionTileTheme ?? this.expansionTileTheme,
floatingActionButtonTheme: floatingActionButtonTheme ?? this.floatingActionButtonTheme,
iconButtonTheme: iconButtonTheme ?? this.iconButtonTheme,
listTileTheme: listTileTheme ?? this.listTileTheme,
navigationBarTheme: navigationBarTheme ?? this.navigationBarTheme,
navigationRailTheme: navigationRailTheme ?? this.navigationRailTheme,
......@@ -2050,6 +2064,7 @@ class ThemeData with Diagnosticable {
elevatedButtonTheme: ElevatedButtonThemeData.lerp(a.elevatedButtonTheme, b.elevatedButtonTheme, t)!,
expansionTileTheme: ExpansionTileThemeData.lerp(a.expansionTileTheme, b.expansionTileTheme, t)!,
floatingActionButtonTheme: FloatingActionButtonThemeData.lerp(a.floatingActionButtonTheme, b.floatingActionButtonTheme, t)!,
iconButtonTheme: IconButtonThemeData.lerp(a.iconButtonTheme, b.iconButtonTheme, t)!,
listTileTheme: ListTileThemeData.lerp(a.listTileTheme, b.listTileTheme, t)!,
navigationBarTheme: NavigationBarThemeData.lerp(a.navigationBarTheme, b.navigationBarTheme, t)!,
navigationRailTheme: NavigationRailThemeData.lerp(a.navigationRailTheme, b.navigationRailTheme, t)!,
......@@ -2150,6 +2165,7 @@ class ThemeData with Diagnosticable {
other.elevatedButtonTheme == elevatedButtonTheme &&
other.expansionTileTheme == expansionTileTheme &&
other.floatingActionButtonTheme == floatingActionButtonTheme &&
other.iconButtonTheme == iconButtonTheme &&
other.listTileTheme == listTileTheme &&
other.navigationBarTheme == navigationBarTheme &&
other.navigationRailTheme == navigationRailTheme &&
......@@ -2247,6 +2263,7 @@ class ThemeData with Diagnosticable {
elevatedButtonTheme,
expansionTileTheme,
floatingActionButtonTheme,
iconButtonTheme,
listTileTheme,
navigationBarTheme,
navigationRailTheme,
......@@ -2346,6 +2363,7 @@ class ThemeData with Diagnosticable {
properties.add(DiagnosticsProperty<ElevatedButtonThemeData>('elevatedButtonTheme', elevatedButtonTheme, defaultValue: defaultData.elevatedButtonTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<ExpansionTileThemeData>('expansionTileTheme', expansionTileTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<FloatingActionButtonThemeData>('floatingActionButtonTheme', floatingActionButtonTheme, defaultValue: defaultData.floatingActionButtonTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<IconButtonThemeData>('iconButtonTheme', iconButtonTheme, defaultValue: defaultData.iconButtonTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<ListTileThemeData>('listTileTheme', listTileTheme, defaultValue: defaultData.listTileTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<NavigationBarThemeData>('navigationBarTheme', navigationBarTheme, defaultValue: defaultData.navigationBarTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<NavigationRailThemeData>('navigationRailTheme', navigationRailTheme, defaultValue: defaultData.navigationRailTheme, level: DiagnosticLevel.debug));
......
......@@ -376,6 +376,22 @@ void main() {
expect(box.size, const Size(96.0, 96.0));
});
testWidgets('test default alignment', (WidgetTester tester) async {
await tester.pumpWidget(
wrap(
useMaterial3: theme.useMaterial3,
child: IconButton(
onPressed: mockOnPressedFunction.handler,
icon: const Icon(Icons.ac_unit),
iconSize: 80.0,
),
),
);
final Align align = tester.firstWidget<Align>(find.ancestor(of: find.byIcon(Icons.ac_unit), matching: find.byType(Align)));
expect(align.alignment, Alignment.center);
});
testWidgets('test tooltip', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
......@@ -977,6 +993,48 @@ void main() {
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.none);
});
testWidgets('IconTheme opacity test', (WidgetTester tester) async {
final ThemeData theme = ThemeData.from(colorScheme: colorScheme, useMaterial3: false);
await tester.pumpWidget(
MaterialApp(
theme: theme,
home: Scaffold(
body: Center(
child: IconButton(
icon: const Icon(Icons.add),
color: Colors.purple,
onPressed: () {},
)
),
),
)
);
Color? iconColor() => _iconStyle(tester, Icons.add)?.color;
expect(iconColor(), Colors.purple);
await tester.pumpWidget(
MaterialApp(
theme: theme,
home: Scaffold(
body: Center(
child: IconTheme.merge(
data: const IconThemeData(opacity: 0.5),
child: IconButton(
icon: const Icon(Icons.add),
color: Colors.purple,
onPressed: () {},
),
)
),
),
)
);
Color? iconColorWithOpacity() => _iconStyle(tester, Icons.add)?.color;
expect(iconColorWithOpacity(), Colors.purple.withOpacity(0.5));
});
testWidgets('IconButton defaults - M3', (WidgetTester tester) async {
final ThemeData themeM3 = ThemeData.from(colorScheme: colorScheme, useMaterial3: true);
......@@ -1013,6 +1071,7 @@ void main() {
final Align align = tester.firstWidget<Align>(find.ancestor(of: find.byIcon(Icons.ac_unit), matching: find.byType(Align)));
expect(align.alignment, Alignment.center);
expect(tester.getSize(find.byIcon(Icons.ac_unit)), const Size(24.0, 24.0));
final Offset center = tester.getCenter(find.byType(IconButton));
final TestGesture gesture = await tester.startGesture(center);
......@@ -1569,6 +1628,194 @@ void main() {
expect(find.byIcon(Icons.account_box), findsNothing);
expect(find.byIcon(Icons.ac_unit), findsOneWidget);
});
group('IconTheme tests in Material 3', () {
testWidgets('IconTheme overrides default values in M3', (WidgetTester tester) async {
// Theme's IconTheme
await tester.pumpWidget(
MaterialApp(
theme: ThemeData.from(
colorScheme: const ColorScheme.light(),
useMaterial3: true,
).copyWith(
iconTheme: const IconThemeData(color: Colors.red, size: 37),
),
home: IconButton(
icon: const Icon(Icons.account_box),
onPressed: () {},
)
)
);
Color? iconColor0() => _iconStyle(tester, Icons.account_box)?.color;
expect(iconColor0(), Colors.red);
expect(tester.getSize(find.byIcon(Icons.account_box)), equals(const Size(37, 37)),);
// custom IconTheme outside of IconButton
await tester.pumpWidget(
MaterialApp(
theme: ThemeData.from(
colorScheme: const ColorScheme.light(),
useMaterial3: true,
),
home: IconTheme.merge(
data: const IconThemeData(color: Colors.pink, size: 35),
child: IconButton(
icon: const Icon(Icons.account_box),
onPressed: () {},
),
)
)
);
Color? iconColor1() => _iconStyle(tester, Icons.account_box)?.color;
expect(iconColor1(), Colors.pink);
expect(tester.getSize(find.byIcon(Icons.account_box)), equals(const Size(35, 35)),);
});
testWidgets('Theme IconButtonTheme overrides IconTheme in Material3', (WidgetTester tester) async {
// When IconButtonTheme and IconTheme both exist in ThemeData, the IconButtonTheme can override IconTheme.
await tester.pumpWidget(
MaterialApp(
theme: ThemeData.from(
colorScheme: const ColorScheme.light(),
useMaterial3: true,
).copyWith(
iconTheme: const IconThemeData(color: Colors.red, size: 25),
iconButtonTheme: IconButtonThemeData(style: IconButton.styleFrom(foregroundColor: Colors.green, iconSize: 27),)
),
home: IconButton(
icon: const Icon(Icons.account_box),
onPressed: () {},
)
)
);
Color? iconColor() => _iconStyle(tester, Icons.account_box)?.color;
expect(iconColor(), Colors.green);
expect(tester.getSize(find.byIcon(Icons.account_box)), equals(const Size(27, 27)),);
});
testWidgets('Button IconButtonTheme always overrides IconTheme in Material3', (WidgetTester tester) async {
// When IconButtonTheme is closer to IconButton, IconButtonTheme overrides IconTheme
await tester.pumpWidget(
MaterialApp(
theme: ThemeData.from(
colorScheme: const ColorScheme.light(),
useMaterial3: true,
),
home: IconTheme.merge(
data: const IconThemeData(color: Colors.orange, size: 36),
child: IconButtonTheme(
data: IconButtonThemeData(style: IconButton.styleFrom(foregroundColor: Colors.blue, iconSize: 35)),
child: IconButton(
icon: const Icon(Icons.account_box),
onPressed: () {},
),
),
)
)
);
Color? iconColor0() => _iconStyle(tester, Icons.account_box)?.color;
expect(iconColor0(), Colors.blue);
expect(tester.getSize(find.byIcon(Icons.account_box)), equals(const Size(35, 35)),);
// When IconTheme is closer to IconButton, IconButtonTheme still overrides IconTheme
await tester.pumpWidget(
MaterialApp(
theme: ThemeData.from(
colorScheme: const ColorScheme.light(),
useMaterial3: true,
),
home: IconTheme.merge(
data: const IconThemeData(color: Colors.blue, size: 35),
child: IconButtonTheme(
data: IconButtonThemeData(style: IconButton.styleFrom(foregroundColor: Colors.orange, iconSize: 36)),
child: IconButton(
icon: const Icon(Icons.account_box),
onPressed: () {},
),
),
)
)
);
Color? iconColor1() => _iconStyle(tester, Icons.account_box)?.color;
expect(iconColor1(), Colors.orange);
expect(tester.getSize(find.byIcon(Icons.account_box)), equals(const Size(36, 36)),);
});
testWidgets('White icon color defined by users shows correctly in Material3', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
theme: ThemeData.from(
colorScheme: const ColorScheme.dark(),
useMaterial3: true,
).copyWith(
iconTheme: const IconThemeData(color: Colors.white),
),
home: IconButton(
icon: const Icon(Icons.account_box),
onPressed: () {},
)
)
);
Color? iconColor1() => _iconStyle(tester, Icons.account_box)?.color;
expect(iconColor1(), Colors.white);
});
testWidgets('In light mode, icon color is M3 default color instead of IconTheme.of(context).color, '
'if only setting color in IconTheme', (WidgetTester tester) async {
final ColorScheme darkScheme = const ColorScheme.dark().copyWith(onSurfaceVariant: const Color(0xffe91e60));
// Brightness.dark
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(colorScheme: darkScheme, useMaterial3: true,),
home: Scaffold(
body: IconTheme.merge(
data: const IconThemeData(size: 26),
child: IconButton(
icon: const Icon(Icons.account_box),
onPressed: () {},
),
),
)
)
);
Color? iconColor0() => _iconStyle(tester, Icons.account_box)?.color;
expect(iconColor0(), darkScheme.onSurfaceVariant); // onSurfaceVariant
});
testWidgets('In dark mode, icon color is M3 default color instead of IconTheme.of(context).color, '
'if only setting color in IconTheme', (WidgetTester tester) async {
final ColorScheme lightScheme = const ColorScheme.light().copyWith(onSurfaceVariant: const Color(0xffe91e60));
// Brightness.dark
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(colorScheme: lightScheme, useMaterial3: true,),
home: Scaffold(
body: IconTheme.merge(
data: const IconThemeData(size: 26),
child: IconButton(
icon: const Icon(Icons.account_box),
onPressed: () {},
),
),
)
)
);
Color? iconColor0() => _iconStyle(tester, Icons.account_box)?.color;
expect(iconColor0(), lightScheme.onSurfaceVariant); // onSurfaceVariant
});
testWidgets('black87 icon color defined by users shows correctly in Material3', (WidgetTester tester) async {
});
});
}
Widget wrap({required Widget child, required bool useMaterial3}) {
......
This diff is collapsed.
......@@ -2511,10 +2511,10 @@ void main() {
}
await buildFrame();
expect(tester.widget<IconButton>(find.byType(IconButton)).iconSize, 24);
expect(tester.getSize(find.byIcon(Icons.adaptive.more)), const Size(24, 24));
await buildFrame(iconSize: 50);
expect(tester.widget<IconButton>(find.byType(IconButton)).iconSize, 50);
expect(tester.getSize(find.byIcon(Icons.adaptive.more)), const Size(50, 50));
});
testWidgets('does not crash in small overlay', (WidgetTester tester) async {
......@@ -2867,23 +2867,20 @@ void main() {
// Popup menu with default icon size.
await tester.pumpWidget(buildPopupMenu());
IconButton iconButton = tester.widget(find.widgetWithIcon(IconButton, Icons.more_vert));
// Default PopupMenuButton icon size is 24.0.
expect(iconButton.iconSize, 24.0);
expect(tester.getSize(find.byIcon(Icons.more_vert)), const Size(24.0, 24.0));
// Popup menu with custom theme icon size.
await tester.pumpWidget(buildPopupMenu(themeIconSize: 30.0));
await tester.pumpAndSettle();
iconButton = tester.widget(find.widgetWithIcon(IconButton, Icons.more_vert));
// PopupMenuButton icon inherits IconTheme's size.
expect(iconButton.iconSize, 30.0);
expect(tester.getSize(find.byIcon(Icons.more_vert)), const Size(30.0, 30.0));
// Popup menu with custom icon size.
await tester.pumpWidget(buildPopupMenu(themeIconSize: 30.0, iconSize: 50.0));
await tester.pumpAndSettle();
iconButton = tester.widget(find.widgetWithIcon(IconButton, Icons.more_vert));
// PopupMenuButton icon size overrides IconTheme's size.
expect(iconButton.iconSize, 50.0);
expect(tester.getSize(find.byIcon(Icons.more_vert)), const Size(50.0, 50.0));
});
testWidgets('Popup menu clip behavior', (WidgetTester tester) async {
......
......@@ -697,6 +697,7 @@ void main() {
elevatedButtonTheme: ElevatedButtonThemeData(style: ElevatedButton.styleFrom(backgroundColor: Colors.green)),
expansionTileTheme: const ExpansionTileThemeData(backgroundColor: Colors.black),
floatingActionButtonTheme: const FloatingActionButtonThemeData(backgroundColor: Colors.black),
iconButtonTheme: IconButtonThemeData(style: IconButton.styleFrom(foregroundColor: Colors.pink)),
listTileTheme: const ListTileThemeData(),
navigationBarTheme: const NavigationBarThemeData(backgroundColor: Colors.black),
navigationRailTheme: const NavigationRailThemeData(backgroundColor: Colors.black),
......@@ -809,6 +810,7 @@ void main() {
elevatedButtonTheme: const ElevatedButtonThemeData(),
expansionTileTheme: const ExpansionTileThemeData(backgroundColor: Colors.black),
floatingActionButtonTheme: const FloatingActionButtonThemeData(backgroundColor: Colors.white),
iconButtonTheme: const IconButtonThemeData(),
listTileTheme: const ListTileThemeData(),
navigationBarTheme: const NavigationBarThemeData(backgroundColor: Colors.white),
navigationRailTheme: const NavigationRailThemeData(backgroundColor: Colors.white),
......@@ -907,6 +909,7 @@ void main() {
elevatedButtonTheme: otherTheme.elevatedButtonTheme,
expansionTileTheme: otherTheme.expansionTileTheme,
floatingActionButtonTheme: otherTheme.floatingActionButtonTheme,
iconButtonTheme: otherTheme.iconButtonTheme,
listTileTheme: otherTheme.listTileTheme,
navigationBarTheme: otherTheme.navigationBarTheme,
navigationRailTheme: otherTheme.navigationRailTheme,
......@@ -1004,6 +1007,7 @@ void main() {
expect(themeDataCopy.elevatedButtonTheme, equals(otherTheme.elevatedButtonTheme));
expect(themeDataCopy.expansionTileTheme, equals(otherTheme.expansionTileTheme));
expect(themeDataCopy.floatingActionButtonTheme, equals(otherTheme.floatingActionButtonTheme));
expect(themeDataCopy.iconButtonTheme, equals(otherTheme.iconButtonTheme));
expect(themeDataCopy.listTileTheme, equals(otherTheme.listTileTheme));
expect(themeDataCopy.navigationBarTheme, equals(otherTheme.navigationBarTheme));
expect(themeDataCopy.navigationRailTheme, equals(otherTheme.navigationRailTheme));
......@@ -1138,6 +1142,7 @@ void main() {
'drawerTheme',
'elevatedButtonTheme',
'floatingActionButtonTheme',
'iconButtonTheme',
'listTileTheme',
'navigationBarTheme',
'navigationRailTheme',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment