Skip to content

Commit 7d9eaab

Browse files
authored
Appbar iconTheme override fix (#118681)
* theme override fix * add conditional centering
1 parent 11d21e0 commit 7d9eaab

File tree

2 files changed

+92
-29
lines changed

2 files changed

+92
-29
lines changed

packages/flutter/lib/src/material/app_bar.dart

+25-29
Original file line numberDiff line numberDiff line change
@@ -1023,39 +1023,35 @@ class _AppBarState extends State<AppBar> {
10231023
}
10241024
if (leading != null) {
10251025
if (theme.useMaterial3) {
1026-
if (leading is IconButton) {
1027-
final IconButtonThemeData effectiveIconButtonTheme;
1028-
1029-
// This comparison is to check if there is a custom [overallIconTheme]. If true, it means that no
1030-
// custom [overallIconTheme] is provided, so [iconButtonTheme] is applied. Otherwise, we generate
1031-
// a new [IconButtonThemeData] based on the values from [overallIconTheme]. If [iconButtonTheme] only
1032-
// has null values, the default [overallIconTheme] will be applied below by [IconTheme.merge]
1033-
if (overallIconTheme == defaults.iconTheme) {
1034-
effectiveIconButtonTheme = iconButtonTheme;
1035-
} else {
1036-
// The [IconButton.styleFrom] method is used to generate a correct [overlayColor] based on the [foregroundColor].
1037-
final ButtonStyle leadingIconButtonStyle = IconButton.styleFrom(
1038-
foregroundColor: overallIconTheme.color,
1039-
iconSize: overallIconTheme.size,
1040-
);
1041-
1042-
effectiveIconButtonTheme = IconButtonThemeData(
1043-
style: iconButtonTheme.style?.copyWith(
1044-
foregroundColor: leadingIconButtonStyle.foregroundColor,
1045-
overlayColor: leadingIconButtonStyle.overlayColor,
1046-
iconSize: leadingIconButtonStyle.iconSize,
1047-
)
1048-
);
1049-
}
1050-
1051-
leading = Center(
1052-
child: IconButtonTheme(
1053-
data: effectiveIconButtonTheme,
1054-
child: leading
1026+
final IconButtonThemeData effectiveIconButtonTheme;
1027+
1028+
// This comparison is to check if there is a custom [overallIconTheme]. If true, it means that no
1029+
// custom [overallIconTheme] is provided, so [iconButtonTheme] is applied. Otherwise, we generate
1030+
// a new [IconButtonThemeData] based on the values from [overallIconTheme]. If [iconButtonTheme] only
1031+
// has null values, the default [overallIconTheme] will be applied below by [IconTheme.merge]
1032+
if (overallIconTheme == defaults.iconTheme) {
1033+
effectiveIconButtonTheme = iconButtonTheme;
1034+
} else {
1035+
// The [IconButton.styleFrom] method is used to generate a correct [overlayColor] based on the [foregroundColor].
1036+
final ButtonStyle leadingIconButtonStyle = IconButton.styleFrom(
1037+
foregroundColor: overallIconTheme.color,
1038+
iconSize: overallIconTheme.size,
1039+
);
1040+
1041+
effectiveIconButtonTheme = IconButtonThemeData(
1042+
style: iconButtonTheme.style?.copyWith(
1043+
foregroundColor: leadingIconButtonStyle.foregroundColor,
1044+
overlayColor: leadingIconButtonStyle.overlayColor,
1045+
iconSize: leadingIconButtonStyle.iconSize,
10551046
)
10561047
);
10571048
}
10581049

1050+
leading = IconButtonTheme(
1051+
data: effectiveIconButtonTheme,
1052+
child: leading is IconButton ? Center(child: leading) : leading,
1053+
);
1054+
10591055
// Based on the Material Design 3 specs, the leading IconButton should have
10601056
// a size of 48x48, and a highlight size of 40x40. Users can also put other
10611057
// type of widgets on leading with the original config.

packages/flutter/test/material/app_bar_test.dart

+67
Original file line numberDiff line numberDiff line change
@@ -3235,6 +3235,39 @@ void main() {
32353235
expect(actionIconButtonSize(), 30.0);
32363236
});
32373237

3238+
testWidgets('AppBar.iconTheme should override any IconButtonTheme present in the theme for widgets containing an iconButton - M3', (WidgetTester tester) async {
3239+
final ThemeData themeData = ThemeData(
3240+
iconButtonTheme: IconButtonThemeData(
3241+
style: IconButton.styleFrom(
3242+
foregroundColor: Colors.red,
3243+
iconSize: 32.0,
3244+
),
3245+
),
3246+
useMaterial3: true,
3247+
);
3248+
3249+
const IconThemeData overallIconTheme = IconThemeData(color: Colors.yellow, size: 30.0);
3250+
await tester.pumpWidget(
3251+
MaterialApp(
3252+
theme: themeData,
3253+
home: Scaffold(
3254+
appBar: AppBar(
3255+
iconTheme: overallIconTheme,
3256+
leading: BackButton(onPressed: () {}),
3257+
title: const Text('title'),
3258+
),
3259+
),
3260+
),
3261+
);
3262+
3263+
Color? leadingIconButtonColor() => iconStyle(tester, Icons.arrow_back)?.color;
3264+
double? leadingIconButtonSize() => iconStyle(tester, Icons.arrow_back)?.fontSize;
3265+
3266+
expect(leadingIconButtonColor(), Colors.yellow);
3267+
expect(leadingIconButtonSize(), 30.0);
3268+
3269+
});
3270+
32383271
testWidgets('AppBar.actionsIconTheme should override any IconButtonTheme present in the theme - M3', (WidgetTester tester) async {
32393272
final ThemeData themeData = ThemeData(
32403273
iconButtonTheme: IconButtonThemeData(
@@ -3275,6 +3308,40 @@ void main() {
32753308
expect(actionIconButtonSize(), 30.0);
32763309
});
32773310

3311+
testWidgets('AppBar.actionsIconTheme should override any IconButtonTheme present in the theme for widgets containing an iconButton - M3', (WidgetTester tester) async {
3312+
final ThemeData themeData = ThemeData(
3313+
iconButtonTheme: IconButtonThemeData(
3314+
style: IconButton.styleFrom(
3315+
foregroundColor: Colors.red,
3316+
iconSize: 32.0,
3317+
),
3318+
),
3319+
useMaterial3: true,
3320+
);
3321+
3322+
const IconThemeData actionsIconTheme = IconThemeData(color: Colors.yellow, size: 30.0);
3323+
await tester.pumpWidget(
3324+
MaterialApp(
3325+
theme: themeData,
3326+
home: Scaffold(
3327+
appBar: AppBar(
3328+
actionsIconTheme: actionsIconTheme,
3329+
title: const Text('title'),
3330+
actions: <Widget>[
3331+
BackButton(onPressed: () {}),
3332+
],
3333+
),
3334+
),
3335+
),
3336+
);
3337+
3338+
Color? actionIconButtonColor() => iconStyle(tester, Icons.arrow_back)?.color;
3339+
double? actionIconButtonSize() => iconStyle(tester, Icons.arrow_back)?.fontSize;
3340+
3341+
expect(actionIconButtonColor(), Colors.yellow);
3342+
expect(actionIconButtonSize(), 30.0);
3343+
});
3344+
32783345
testWidgets('The foregroundColor property of the AppBar overrides any IconButtonTheme present in the theme - M3', (WidgetTester tester) async {
32793346
final ThemeData themeData = ThemeData(
32803347
iconButtonTheme: IconButtonThemeData(

0 commit comments

Comments
 (0)