Fix IconButton theming in the InputDecorator (#146567)

fixes [DropdownMenu TrailingIcon can't be styled through providing an IconButtonTheme](https://github.com/flutter/flutter/issues/145081) (second PR)

### Description
 This PR replaces `IconButton.style`  with `ButtonStyle` when merging parent `IconButtonTheme`  as `styleFrom` returns defaults for some properties.
This commit is contained in:
Taha Tesser 2024-04-11 10:15:24 +03:00 committed by GitHub
parent 61cbe2f5b7
commit 831226aada
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 91 additions and 24 deletions

View file

@ -9,10 +9,10 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'button_style.dart';
import 'color_scheme.dart';
import 'colors.dart';
import 'constants.dart';
import 'icon_button.dart';
import 'icon_button_theme.dart';
import 'input_border.dart';
import 'material.dart';
@ -2245,9 +2245,11 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
),
child: IconButtonTheme(
data: IconButtonThemeData(
style: IconButton.styleFrom(
foregroundColor: _getPrefixIconColor(inputDecorationTheme, iconButtonTheme, defaults),
iconSize: iconSize,
style: ButtonStyle(
foregroundColor: WidgetStatePropertyAll<Color>(
_getPrefixIconColor(inputDecorationTheme, iconButtonTheme, defaults),
),
iconSize: WidgetStatePropertyAll<double>(iconSize),
).merge(iconButtonTheme.style),
),
child: Semantics(
@ -2280,9 +2282,11 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
),
child: IconButtonTheme(
data: IconButtonThemeData(
style: IconButton.styleFrom(
foregroundColor: _getSuffixIconColor(inputDecorationTheme, iconButtonTheme, defaults),
iconSize: iconSize,
style: ButtonStyle(
foregroundColor: WidgetStatePropertyAll<Color>(
_getSuffixIconColor(inputDecorationTheme, iconButtonTheme, defaults),
),
iconSize: WidgetStatePropertyAll<double>(iconSize),
).merge(iconButtonTheme.style),
),
child: Semantics(

View file

@ -292,6 +292,10 @@ TextStyle? getIconStyle(WidgetTester tester, IconData icon) {
return iconRichText.text.style;
}
RenderObject getOverlayColor(WidgetTester tester) {
return tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
}
void main() {
// TODO(bleroux): migrate all M2 tests to M3.
// See https://github.com/flutter/flutter/issues/139076
@ -5078,18 +5082,23 @@ void main() {
expect(merged.constraints, overrideTheme.constraints);
});
testWidgets('Prefix and suffix IconButtons inherit IconButtonTheme', (WidgetTester tester) async {
testWidgets('Prefix IconButton inherits IconButtonTheme', (WidgetTester tester) async {
const IconData prefixIcon = Icons.person;
const IconData suffixIcon = Icons.search;
const Color backgroundColor = Color(0xffff0000);
const Color foregroundColor = Color(0xff00ff00);
final OutlinedBorder shape =RoundedRectangleBorder(
const Color overlayColor = Color(0xff0000ff);
const Color shadowColor = Color(0xff0ff0ff);
const double elevation = 4.0;
final RoundedRectangleBorder shape = RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
);
final ButtonStyle iconButtonStyle = IconButton.styleFrom(
backgroundColor: backgroundColor,
foregroundColor: foregroundColor,
shape: shape,
final ButtonStyle iconButtonStyle = ButtonStyle(
backgroundColor: const MaterialStatePropertyAll<Color>(backgroundColor),
foregroundColor: const MaterialStatePropertyAll<Color>(foregroundColor),
overlayColor: const MaterialStatePropertyAll<Color>(overlayColor),
shadowColor: const MaterialStatePropertyAll<Color>(shadowColor),
elevation: const MaterialStatePropertyAll<double>(elevation),
shape: MaterialStatePropertyAll<OutlinedBorder>(shape),
);
await tester.pumpWidget(
@ -5101,6 +5110,57 @@ void main() {
onPressed: () {},
icon: const Icon(prefixIcon),
),
),
),
),
);
final Finder iconMaterial = find.descendant(
of: find.widgetWithIcon(IconButton, prefixIcon),
matching: find.byType(Material),
);
final Material material = tester.widget<Material>(iconMaterial);
expect(material.color, backgroundColor);
expect(material.shadowColor, shadowColor);
expect(material.elevation, elevation);
expect(material.shape, shape);
expect(getIconStyle(tester, prefixIcon)?.color, foregroundColor);
final Offset center = tester.getCenter(find.byIcon(prefixIcon));
final TestGesture gesture = await tester.createGesture(
kind: PointerDeviceKind.mouse,
);
await gesture.addPointer();
await gesture.moveTo(center);
await tester.pumpAndSettle();
expect(getOverlayColor(tester), paints..rect(color: overlayColor));
});
testWidgets('Suffix IconButton inherits IconButtonTheme', (WidgetTester tester) async {
const IconData suffixIcon = Icons.delete;
const Color backgroundColor = Color(0xffff0000);
const Color foregroundColor = Color(0xff00ff00);
const Color overlayColor = Color(0xff0000ff);
const Color shadowColor = Color(0xff0ff0ff);
const double elevation = 4.0;
final RoundedRectangleBorder shape = RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
);
final ButtonStyle iconButtonStyle = ButtonStyle(
backgroundColor: const MaterialStatePropertyAll<Color>(backgroundColor),
foregroundColor: const MaterialStatePropertyAll<Color>(foregroundColor),
overlayColor: const MaterialStatePropertyAll<Color>(overlayColor),
shadowColor: const MaterialStatePropertyAll<Color>(shadowColor),
elevation: const MaterialStatePropertyAll<double>(elevation),
shape: MaterialStatePropertyAll<OutlinedBorder>(shape),
);
await tester.pumpWidget(
IconButtonTheme(
data: IconButtonThemeData(style: iconButtonStyle),
child: buildInputDecorator(
decoration: InputDecoration(
suffixIcon: IconButton(
onPressed: () {},
icon: const Icon(suffixIcon),
@ -5110,23 +5170,26 @@ void main() {
),
);
final Finder prefixIconMaterial = find.descendant(
of: find.widgetWithIcon(IconButton, prefixIcon),
matching: find.byType(Material),
);
Material material = tester.widget<Material>(prefixIconMaterial);
expect(material.color, backgroundColor);
expect(material.shape, iconButtonStyle.shape?.resolve(<WidgetState>{}));
final Finder suffixIconMaterial = find.descendant(
final Finder iconMaterial = find.descendant(
of: find.widgetWithIcon(IconButton, suffixIcon),
matching: find.byType(Material),
);
material = tester.widget<Material>(suffixIconMaterial);
final Material material = tester.widget<Material>(iconMaterial);
expect(material.color, backgroundColor);
expect(material.shadowColor, shadowColor);
expect(material.elevation, elevation);
expect(material.shape, shape);
expect(getIconStyle(tester, prefixIcon)?.color, foregroundColor);
expect(getIconStyle(tester, suffixIcon)?.color, foregroundColor);
final Offset center = tester.getCenter(find.byIcon(suffixIcon));
final TestGesture gesture = await tester.createGesture(
kind: PointerDeviceKind.mouse,
);
await gesture.addPointer();
await gesture.moveTo(center);
await tester.pumpAndSettle();
expect(getOverlayColor(tester), paints..rect(color: overlayColor));
});
testWidgets('Prefix IconButton color respects IconButtonTheme foreground color states', (WidgetTester tester) async {