Unverified Commit 2719f65b authored by Viren Khatri's avatar Viren Khatri Committed by GitHub

Updated IconButton.iconSize to get value from theme (#87643)

parent c7572150
...@@ -116,7 +116,7 @@ class IconButton extends StatelessWidget { ...@@ -116,7 +116,7 @@ class IconButton extends StatelessWidget {
/// or an [ImageIcon]. /// or an [ImageIcon].
const IconButton({ const IconButton({
Key? key, Key? key,
this.iconSize = 24.0, this.iconSize,
this.visualDensity, this.visualDensity,
this.padding = const EdgeInsets.all(8.0), this.padding = const EdgeInsets.all(8.0),
this.alignment = Alignment.center, this.alignment = Alignment.center,
...@@ -135,8 +135,7 @@ class IconButton extends StatelessWidget { ...@@ -135,8 +135,7 @@ class IconButton extends StatelessWidget {
this.enableFeedback = true, this.enableFeedback = true,
this.constraints, this.constraints,
required this.icon, required this.icon,
}) : assert(iconSize != null), }) : assert(padding != null),
assert(padding != null),
assert(alignment != null), assert(alignment != null),
assert(splashRadius == null || splashRadius > 0), assert(splashRadius == null || splashRadius > 0),
assert(autofocus != null), assert(autofocus != null),
...@@ -145,7 +144,8 @@ class IconButton extends StatelessWidget { ...@@ -145,7 +144,8 @@ class IconButton extends StatelessWidget {
/// The size of the icon inside the button. /// The size of the icon inside the button.
/// ///
/// This property must not be null. It defaults to 24.0. /// If null, uses [IconThemeData.size]. If it is also null, the default size
/// is 24.0.
/// ///
/// The size given here is passed down to the widget in the [icon] property /// The size given here is passed down to the widget in the [icon] property
/// via an [IconTheme]. Setting the size here instead of in, for example, the /// via an [IconTheme]. Setting the size here instead of in, for example, the
...@@ -153,7 +153,7 @@ class IconButton extends StatelessWidget { ...@@ -153,7 +153,7 @@ class IconButton extends StatelessWidget {
/// fit the [Icon]. If you were to set the size of the [Icon] using /// fit the [Icon]. If you were to set the size of the [Icon] using
/// [Icon.size] instead, then the [IconButton] would default to 24.0 and then /// [Icon.size] instead, then the [IconButton] would default to 24.0 and then
/// the [Icon] itself would likely get clipped. /// the [Icon] itself would likely get clipped.
final double iconSize; final double? iconSize;
/// Defines how compact the icon button's layout will be. /// Defines how compact the icon button's layout will be.
/// ///
...@@ -319,19 +319,20 @@ class IconButton extends StatelessWidget { ...@@ -319,19 +319,20 @@ class IconButton extends StatelessWidget {
minHeight: _kMinButtonSize, minHeight: _kMinButtonSize,
); );
final BoxConstraints adjustedConstraints = effectiveVisualDensity.effectiveConstraints(unadjustedConstraints); final BoxConstraints adjustedConstraints = effectiveVisualDensity.effectiveConstraints(unadjustedConstraints);
final double effectiveIconSize = iconSize ?? IconTheme.of(context).size ?? 24.0;
Widget result = ConstrainedBox( Widget result = ConstrainedBox(
constraints: adjustedConstraints, constraints: adjustedConstraints,
child: Padding( child: Padding(
padding: padding, padding: padding,
child: SizedBox( child: SizedBox(
height: iconSize, height: effectiveIconSize,
width: iconSize, width: effectiveIconSize,
child: Align( child: Align(
alignment: alignment, alignment: alignment,
child: IconTheme.merge( child: IconTheme.merge(
data: IconThemeData( data: IconThemeData(
size: iconSize, size: effectiveIconSize,
color: currentColor, color: currentColor,
), ),
child: icon, child: icon,
...@@ -364,7 +365,7 @@ class IconButton extends StatelessWidget { ...@@ -364,7 +365,7 @@ class IconButton extends StatelessWidget {
splashColor: splashColor ?? theme.splashColor, splashColor: splashColor ?? theme.splashColor,
radius: splashRadius ?? math.max( radius: splashRadius ?? math.max(
Material.defaultSplashRadius, Material.defaultSplashRadius,
(iconSize + math.min(padding.horizontal, padding.vertical)) * 0.7, (effectiveIconSize + math.min(padding.horizontal, padding.vertical)) * 0.7,
// x 0.5 for diameter -> radius and + 40% overflow derived from other Material apps. // x 0.5 for diameter -> radius and + 40% overflow derived from other Material apps.
), ),
child: result, child: result,
......
...@@ -75,6 +75,119 @@ void main() { ...@@ -75,6 +75,119 @@ void main() {
expect(iconButton.size, const Size(70.0, 70.0)); expect(iconButton.size, const Size(70.0, 70.0));
}); });
testWidgets('when both iconSize and IconTheme.of(context).size are null, size falls back to 24.0', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(debugLabel: 'Ink Focus');
await tester.pumpWidget(
wrap(
child: IconTheme(
data: const IconThemeData(size: null),
child: IconButton(
focusNode: focusNode,
onPressed: mockOnPressedFunction.handler,
icon: const Icon(Icons.link),
),
)
),
);
final RenderBox icon = tester.renderObject(find.byType(Icon));
expect(icon.size, const Size(24.0, 24.0));
});
testWidgets('when null, iconSize is overridden by closest IconTheme', (WidgetTester tester) async {
RenderBox icon;
await tester.pumpWidget(
wrap(
child: IconTheme(
data: const IconThemeData(size: 10),
child: IconButton(
onPressed: mockOnPressedFunction.handler,
icon: const Icon(Icons.link),
),
)
),
);
icon = tester.renderObject(find.byType(Icon));
expect(icon.size, const Size(10.0, 10.0));
await tester.pumpWidget(
wrap(
child: Theme(
data: ThemeData(
iconTheme: const IconThemeData(size: 10),
),
child: IconButton(
onPressed: mockOnPressedFunction.handler,
icon: const Icon(Icons.link),
),
)
),
);
icon = tester.renderObject(find.byType(Icon));
expect(icon.size, const Size(10.0, 10.0));
await tester.pumpWidget(
wrap(
child: Theme(
data: ThemeData(
iconTheme: const IconThemeData(size: 20),
),
child: IconTheme(
data: const IconThemeData(size: 10),
child: IconButton(
onPressed: mockOnPressedFunction.handler,
icon: const Icon(Icons.link),
),
),
)
),
);
icon = tester.renderObject(find.byType(Icon));
expect(icon.size, const Size(10.0, 10.0));
await tester.pumpWidget(
wrap(
child: IconTheme(
data: const IconThemeData(size: 20),
child: Theme(
data: ThemeData(
iconTheme: const IconThemeData(size: 10),
),
child: IconButton(
onPressed: mockOnPressedFunction.handler,
icon: const Icon(Icons.link),
),
),
)
),
);
icon = tester.renderObject(find.byType(Icon));
expect(icon.size, const Size(10.0, 10.0));
});
testWidgets('when non-null, iconSize precedes IconTheme.of(context).size', (WidgetTester tester) async {
await tester.pumpWidget(
wrap(
child: IconTheme(
data: const IconThemeData(size: 30.0),
child: IconButton(
iconSize: 10.0,
onPressed: mockOnPressedFunction.handler,
icon: const Icon(Icons.link),
),
)
),
);
final RenderBox icon = tester.renderObject(find.byType(Icon));
expect(icon.size, const Size(10.0, 10.0));
});
testWidgets('Small icons with non-null constraints can be <48dp', (WidgetTester tester) async { testWidgets('Small icons with non-null constraints can be <48dp', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
wrap( wrap(
......
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