mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Add splashRadius
property to IconTheme
(#93478)
This commit is contained in:
parent
b865e23aeb
commit
ed8468b9f0
@ -29,7 +29,7 @@ class CupertinoIconThemeData extends IconThemeData with Diagnosticable {
|
||||
/// Creates a copy of this icon theme but with the given fields replaced with
|
||||
/// the new values.
|
||||
@override
|
||||
CupertinoIconThemeData copyWith({ Color? color, double? opacity, double? size }) {
|
||||
CupertinoIconThemeData copyWith({ Color? color, double? opacity, double? size, double? splashRadius }) {
|
||||
return CupertinoIconThemeData(
|
||||
color: color ?? this.color,
|
||||
opacity: opacity ?? this.opacity,
|
||||
|
@ -306,6 +306,7 @@ class IconButton extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
assert(debugCheckHasMaterial(context));
|
||||
final ThemeData theme = Theme.of(context);
|
||||
final IconThemeData iconTheme = IconTheme.of(context);
|
||||
Color? currentColor;
|
||||
if (onPressed != null)
|
||||
currentColor = color;
|
||||
@ -319,7 +320,7 @@ class IconButton extends StatelessWidget {
|
||||
minHeight: _kMinButtonSize,
|
||||
);
|
||||
final BoxConstraints adjustedConstraints = effectiveVisualDensity.effectiveConstraints(unadjustedConstraints);
|
||||
final double effectiveIconSize = iconSize ?? IconTheme.of(context).size ?? 24.0;
|
||||
final double effectiveIconSize = iconSize ?? iconTheme.size ?? 24.0;
|
||||
|
||||
Widget result = ConstrainedBox(
|
||||
constraints: adjustedConstraints,
|
||||
@ -363,11 +364,12 @@ class IconButton extends StatelessWidget {
|
||||
hoverColor: hoverColor ?? theme.hoverColor,
|
||||
highlightColor: highlightColor ?? theme.highlightColor,
|
||||
splashColor: splashColor ?? theme.splashColor,
|
||||
radius: splashRadius ?? math.max(
|
||||
Material.defaultSplashRadius,
|
||||
(effectiveIconSize + math.min(padding.horizontal, padding.vertical)) * 0.7,
|
||||
// x 0.5 for diameter -> radius and + 40% overflow derived from other Material apps.
|
||||
),
|
||||
radius: splashRadius ?? iconTheme.splashRadius ??
|
||||
math.max(
|
||||
Material.defaultSplashRadius,
|
||||
(effectiveIconSize + math.min(padding.horizontal, padding.vertical)) * 0.7,
|
||||
// x 0.5 for diameter -> radius and + 40% overflow derived from other Material apps.
|
||||
),
|
||||
child: result,
|
||||
),
|
||||
);
|
||||
|
@ -23,7 +23,7 @@ class IconThemeData with Diagnosticable {
|
||||
///
|
||||
/// The opacity applies to both explicit and default icon colors. The value
|
||||
/// is clamped between 0.0 and 1.0.
|
||||
const IconThemeData({this.color, double? opacity, this.size}) : _opacity = opacity;
|
||||
const IconThemeData({this.color, double? opacity, this.size, this.splashRadius}) : _opacity = opacity;
|
||||
|
||||
/// Creates an icon theme with some reasonable default values.
|
||||
///
|
||||
@ -31,15 +31,17 @@ class IconThemeData with Diagnosticable {
|
||||
const IconThemeData.fallback()
|
||||
: color = const Color(0xFF000000),
|
||||
_opacity = 1.0,
|
||||
size = 24.0;
|
||||
size = 24.0,
|
||||
splashRadius = null;
|
||||
|
||||
/// Creates a copy of this icon theme but with the given fields replaced with
|
||||
/// the new values.
|
||||
IconThemeData copyWith({ Color? color, double? opacity, double? size }) {
|
||||
IconThemeData copyWith({ Color? color, double? opacity, double? size, double? splashRadius }) {
|
||||
return IconThemeData(
|
||||
color: color ?? this.color,
|
||||
opacity: opacity ?? this.opacity,
|
||||
size: size ?? this.size,
|
||||
splashRadius: splashRadius ?? this.splashRadius,
|
||||
);
|
||||
}
|
||||
|
||||
@ -53,6 +55,7 @@ class IconThemeData with Diagnosticable {
|
||||
color: other.color,
|
||||
opacity: other.opacity,
|
||||
size: other.size,
|
||||
splashRadius: other.splashRadius,
|
||||
);
|
||||
}
|
||||
|
||||
@ -87,6 +90,9 @@ class IconThemeData with Diagnosticable {
|
||||
/// The default size for icons.
|
||||
final double? size;
|
||||
|
||||
/// The default splash radius for [IconButton]s.
|
||||
final double? splashRadius;
|
||||
|
||||
/// Linearly interpolate between two icon theme data objects.
|
||||
///
|
||||
/// {@macro dart.ui.shadow.lerp}
|
||||
@ -96,6 +102,7 @@ class IconThemeData with Diagnosticable {
|
||||
color: Color.lerp(a?.color, b?.color, t),
|
||||
opacity: ui.lerpDouble(a?.opacity, b?.opacity, t),
|
||||
size: ui.lerpDouble(a?.size, b?.size, t),
|
||||
splashRadius: ui.lerpDouble(a?.splashRadius, b?.splashRadius, t),
|
||||
);
|
||||
}
|
||||
|
||||
@ -106,11 +113,12 @@ class IconThemeData with Diagnosticable {
|
||||
return other is IconThemeData
|
||||
&& other.color == color
|
||||
&& other.opacity == opacity
|
||||
&& other.size == size;
|
||||
&& other.size == size
|
||||
&& other.splashRadius == splashRadius;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(color, opacity, size);
|
||||
int get hashCode => hashValues(color, opacity, size, splashRadius);
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
@ -118,5 +126,6 @@ class IconThemeData with Diagnosticable {
|
||||
properties.add(ColorProperty('color', color, defaultValue: null));
|
||||
properties.add(DoubleProperty('opacity', opacity, defaultValue: null));
|
||||
properties.add(DoubleProperty('size', size, defaultValue: null));
|
||||
properties.add(DoubleProperty('splashRadius', splashRadius, defaultValue: null));
|
||||
}
|
||||
}
|
||||
|
@ -480,6 +480,40 @@ void main() {
|
||||
await gesture.up();
|
||||
});
|
||||
|
||||
testWidgets('IconButton can inherit splashRadius from IconTheme', (WidgetTester tester) async {
|
||||
const double splashRadius = 30.0;
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Material(
|
||||
child: Center(
|
||||
child: IconTheme(
|
||||
data: const IconThemeData(
|
||||
splashRadius: splashRadius,
|
||||
),
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.android),
|
||||
onPressed: () { /* enable the button */ },
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final Offset center = tester.getCenter(find.byType(IconButton));
|
||||
final TestGesture gesture = await tester.startGesture(center);
|
||||
await tester.pump(); // Start gesture.
|
||||
await tester.pump(const Duration(milliseconds: 1000)); // Wait for splash to be well under way.
|
||||
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(IconButton))),
|
||||
paints
|
||||
..circle(radius: splashRadius),
|
||||
);
|
||||
|
||||
await gesture.up();
|
||||
});
|
||||
|
||||
testWidgets('IconButton Semantics (enabled)', (WidgetTester tester) async {
|
||||
final SemanticsTester semantics = SemanticsTester(tester);
|
||||
|
||||
|
@ -7,7 +7,7 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
test('IconThemeData control test', () {
|
||||
const IconThemeData data = IconThemeData(color: Color(0xAAAAAAAA), opacity: 0.5, size: 16.0);
|
||||
const IconThemeData data = IconThemeData(color: Color(0xAAAAAAAA), opacity: 0.5, size: 16.0, splashRadius: 30.0);
|
||||
|
||||
expect(data, hasOneLineDescription);
|
||||
expect(data, equals(data.copyWith()));
|
||||
@ -17,24 +17,27 @@ void main() {
|
||||
expect(lerped.color, const Color(0xBF7F7F7F));
|
||||
expect(lerped.opacity, 0.625);
|
||||
expect(lerped.size, 18.0);
|
||||
expect(lerped.splashRadius, 22.5);
|
||||
});
|
||||
|
||||
test('IconThemeData lerp with first null', () {
|
||||
const IconThemeData data = IconThemeData(color: Color(0xFFFFFFFF), opacity: 1.0, size: 16.0);
|
||||
const IconThemeData data = IconThemeData(color: Color(0xFFFFFFFF), opacity: 1.0, size: 16.0, splashRadius: 30.0);
|
||||
|
||||
final IconThemeData lerped = IconThemeData.lerp(null, data, 0.25);
|
||||
expect(lerped.color, const Color(0x40FFFFFF));
|
||||
expect(lerped.opacity, 0.25);
|
||||
expect(lerped.size, 4.0);
|
||||
expect(lerped.splashRadius, 7.5);
|
||||
});
|
||||
|
||||
test('IconThemeData lerp with second null', () {
|
||||
const IconThemeData data = IconThemeData(color: Color(0xFFFFFFFF), opacity: 1.0, size: 16.0);
|
||||
const IconThemeData data = IconThemeData(color: Color(0xFFFFFFFF), opacity: 1.0, size: 16.0, splashRadius: 30.0);
|
||||
|
||||
final IconThemeData lerped = IconThemeData.lerp(data, null, 0.25);
|
||||
expect(lerped.color, const Color(0xBFFFFFFF));
|
||||
expect(lerped.opacity, 0.75);
|
||||
expect(lerped.size, 12.0);
|
||||
expect(lerped.splashRadius, 22.5);
|
||||
});
|
||||
|
||||
test('IconThemeData lerp with both null', () {
|
||||
@ -42,5 +45,6 @@ void main() {
|
||||
expect(lerped.color, null);
|
||||
expect(lerped.opacity, null);
|
||||
expect(lerped.size, null);
|
||||
expect(lerped.splashRadius, null);
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user