Skip to content

Commit 831226a

Browse files
authored
Fix IconButton theming in the InputDecorator (#146567)
fixes [DropdownMenu TrailingIcon can't be styled through providing an IconButtonTheme](flutter/flutter#145081) (second PR) ### Description This PR replaces `IconButton.style` with `ButtonStyle` when merging parent `IconButtonTheme` as `styleFrom` returns defaults for some properties.
1 parent 61cbe2f commit 831226a

File tree

2 files changed

+91
-24
lines changed

2 files changed

+91
-24
lines changed

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

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import 'package:flutter/foundation.dart';
99
import 'package:flutter/rendering.dart';
1010
import 'package:flutter/widgets.dart';
1111

12+
import 'button_style.dart';
1213
import 'color_scheme.dart';
1314
import 'colors.dart';
1415
import 'constants.dart';
15-
import 'icon_button.dart';
1616
import 'icon_button_theme.dart';
1717
import 'input_border.dart';
1818
import 'material.dart';
@@ -2245,9 +2245,11 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
22452245
),
22462246
child: IconButtonTheme(
22472247
data: IconButtonThemeData(
2248-
style: IconButton.styleFrom(
2249-
foregroundColor: _getPrefixIconColor(inputDecorationTheme, iconButtonTheme, defaults),
2250-
iconSize: iconSize,
2248+
style: ButtonStyle(
2249+
foregroundColor: WidgetStatePropertyAll<Color>(
2250+
_getPrefixIconColor(inputDecorationTheme, iconButtonTheme, defaults),
2251+
),
2252+
iconSize: WidgetStatePropertyAll<double>(iconSize),
22512253
).merge(iconButtonTheme.style),
22522254
),
22532255
child: Semantics(
@@ -2280,9 +2282,11 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
22802282
),
22812283
child: IconButtonTheme(
22822284
data: IconButtonThemeData(
2283-
style: IconButton.styleFrom(
2284-
foregroundColor: _getSuffixIconColor(inputDecorationTheme, iconButtonTheme, defaults),
2285-
iconSize: iconSize,
2285+
style: ButtonStyle(
2286+
foregroundColor: WidgetStatePropertyAll<Color>(
2287+
_getSuffixIconColor(inputDecorationTheme, iconButtonTheme, defaults),
2288+
),
2289+
iconSize: WidgetStatePropertyAll<double>(iconSize),
22862290
).merge(iconButtonTheme.style),
22872291
),
22882292
child: Semantics(

packages/flutter/test/material/input_decorator_test.dart

Lines changed: 80 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,10 @@ TextStyle? getIconStyle(WidgetTester tester, IconData icon) {
292292
return iconRichText.text.style;
293293
}
294294

295+
RenderObject getOverlayColor(WidgetTester tester) {
296+
return tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
297+
}
298+
295299
void main() {
296300
// TODO(bleroux): migrate all M2 tests to M3.
297301
// See https://github.com/flutter/flutter/issues/139076
@@ -5078,18 +5082,23 @@ void main() {
50785082
expect(merged.constraints, overrideTheme.constraints);
50795083
});
50805084

5081-
testWidgets('Prefix and suffix IconButtons inherit IconButtonTheme', (WidgetTester tester) async {
5085+
testWidgets('Prefix IconButton inherits IconButtonTheme', (WidgetTester tester) async {
50825086
const IconData prefixIcon = Icons.person;
5083-
const IconData suffixIcon = Icons.search;
50845087
const Color backgroundColor = Color(0xffff0000);
50855088
const Color foregroundColor = Color(0xff00ff00);
5086-
final OutlinedBorder shape =RoundedRectangleBorder(
5089+
const Color overlayColor = Color(0xff0000ff);
5090+
const Color shadowColor = Color(0xff0ff0ff);
5091+
const double elevation = 4.0;
5092+
final RoundedRectangleBorder shape = RoundedRectangleBorder(
50875093
borderRadius: BorderRadius.circular(10.0),
50885094
);
5089-
final ButtonStyle iconButtonStyle = IconButton.styleFrom(
5090-
backgroundColor: backgroundColor,
5091-
foregroundColor: foregroundColor,
5092-
shape: shape,
5095+
final ButtonStyle iconButtonStyle = ButtonStyle(
5096+
backgroundColor: const MaterialStatePropertyAll<Color>(backgroundColor),
5097+
foregroundColor: const MaterialStatePropertyAll<Color>(foregroundColor),
5098+
overlayColor: const MaterialStatePropertyAll<Color>(overlayColor),
5099+
shadowColor: const MaterialStatePropertyAll<Color>(shadowColor),
5100+
elevation: const MaterialStatePropertyAll<double>(elevation),
5101+
shape: MaterialStatePropertyAll<OutlinedBorder>(shape),
50935102
);
50945103

50955104
await tester.pumpWidget(
@@ -5101,32 +5110,86 @@ void main() {
51015110
onPressed: () {},
51025111
icon: const Icon(prefixIcon),
51035112
),
5104-
suffixIcon: IconButton(
5105-
onPressed: () {},
5106-
icon: const Icon(suffixIcon),
5107-
),
51085113
),
51095114
),
51105115
),
51115116
);
51125117

5113-
final Finder prefixIconMaterial = find.descendant(
5118+
final Finder iconMaterial = find.descendant(
51145119
of: find.widgetWithIcon(IconButton, prefixIcon),
51155120
matching: find.byType(Material),
51165121
);
5117-
Material material = tester.widget<Material>(prefixIconMaterial);
5122+
final Material material = tester.widget<Material>(iconMaterial);
51185123
expect(material.color, backgroundColor);
5119-
expect(material.shape, iconButtonStyle.shape?.resolve(<WidgetState>{}));
5120-
final Finder suffixIconMaterial = find.descendant(
5124+
expect(material.shadowColor, shadowColor);
5125+
expect(material.elevation, elevation);
5126+
expect(material.shape, shape);
5127+
5128+
expect(getIconStyle(tester, prefixIcon)?.color, foregroundColor);
5129+
5130+
final Offset center = tester.getCenter(find.byIcon(prefixIcon));
5131+
final TestGesture gesture = await tester.createGesture(
5132+
kind: PointerDeviceKind.mouse,
5133+
);
5134+
await gesture.addPointer();
5135+
await gesture.moveTo(center);
5136+
await tester.pumpAndSettle();
5137+
expect(getOverlayColor(tester), paints..rect(color: overlayColor));
5138+
});
5139+
5140+
testWidgets('Suffix IconButton inherits IconButtonTheme', (WidgetTester tester) async {
5141+
const IconData suffixIcon = Icons.delete;
5142+
const Color backgroundColor = Color(0xffff0000);
5143+
const Color foregroundColor = Color(0xff00ff00);
5144+
const Color overlayColor = Color(0xff0000ff);
5145+
const Color shadowColor = Color(0xff0ff0ff);
5146+
const double elevation = 4.0;
5147+
final RoundedRectangleBorder shape = RoundedRectangleBorder(
5148+
borderRadius: BorderRadius.circular(10.0),
5149+
);
5150+
final ButtonStyle iconButtonStyle = ButtonStyle(
5151+
backgroundColor: const MaterialStatePropertyAll<Color>(backgroundColor),
5152+
foregroundColor: const MaterialStatePropertyAll<Color>(foregroundColor),
5153+
overlayColor: const MaterialStatePropertyAll<Color>(overlayColor),
5154+
shadowColor: const MaterialStatePropertyAll<Color>(shadowColor),
5155+
elevation: const MaterialStatePropertyAll<double>(elevation),
5156+
shape: MaterialStatePropertyAll<OutlinedBorder>(shape),
5157+
);
5158+
5159+
await tester.pumpWidget(
5160+
IconButtonTheme(
5161+
data: IconButtonThemeData(style: iconButtonStyle),
5162+
child: buildInputDecorator(
5163+
decoration: InputDecoration(
5164+
suffixIcon: IconButton(
5165+
onPressed: () {},
5166+
icon: const Icon(suffixIcon),
5167+
),
5168+
),
5169+
),
5170+
),
5171+
);
5172+
5173+
final Finder iconMaterial = find.descendant(
51215174
of: find.widgetWithIcon(IconButton, suffixIcon),
51225175
matching: find.byType(Material),
51235176
);
5124-
material = tester.widget<Material>(suffixIconMaterial);
5177+
final Material material = tester.widget<Material>(iconMaterial);
51255178
expect(material.color, backgroundColor);
5179+
expect(material.shadowColor, shadowColor);
5180+
expect(material.elevation, elevation);
51265181
expect(material.shape, shape);
51275182

5128-
expect(getIconStyle(tester, prefixIcon)?.color, foregroundColor);
51295183
expect(getIconStyle(tester, suffixIcon)?.color, foregroundColor);
5184+
5185+
final Offset center = tester.getCenter(find.byIcon(suffixIcon));
5186+
final TestGesture gesture = await tester.createGesture(
5187+
kind: PointerDeviceKind.mouse,
5188+
);
5189+
await gesture.addPointer();
5190+
await gesture.moveTo(center);
5191+
await tester.pumpAndSettle();
5192+
expect(getOverlayColor(tester), paints..rect(color: overlayColor));
51305193
});
51315194

51325195
testWidgets('Prefix IconButton color respects IconButtonTheme foreground color states', (WidgetTester tester) async {

0 commit comments

Comments
 (0)