Add missing parameters to RadioListTile
(#120117)
This commit is contained in:
parent
3a514175d3
commit
51227a9a50
@ -264,10 +264,12 @@ class Radio<T> extends StatefulWidget {
|
|||||||
/// [ThemeData.focusColor] is used.
|
/// [ThemeData.focusColor] is used.
|
||||||
final Color? focusColor;
|
final Color? focusColor;
|
||||||
|
|
||||||
|
/// {@template flutter.material.radio.hoverColor}
|
||||||
/// The color for the radio's [Material] when a pointer is hovering over it.
|
/// The color for the radio's [Material] when a pointer is hovering over it.
|
||||||
///
|
///
|
||||||
/// If [overlayColor] returns a non-null color in the [MaterialState.hovered]
|
/// If [overlayColor] returns a non-null color in the [MaterialState.hovered]
|
||||||
/// state, it will be used instead.
|
/// state, it will be used instead.
|
||||||
|
/// {@endtemplate}
|
||||||
///
|
///
|
||||||
/// If null, then the value of [RadioThemeData.overlayColor] is used in the
|
/// If null, then the value of [RadioThemeData.overlayColor] is used in the
|
||||||
/// hovered state. If that is also null, then the value of
|
/// hovered state. If that is also null, then the value of
|
||||||
@ -275,7 +277,7 @@ class Radio<T> extends StatefulWidget {
|
|||||||
final Color? hoverColor;
|
final Color? hoverColor;
|
||||||
|
|
||||||
/// {@template flutter.material.radio.overlayColor}
|
/// {@template flutter.material.radio.overlayColor}
|
||||||
/// The color for the checkbox's [Material].
|
/// The color for the radio's [Material].
|
||||||
///
|
///
|
||||||
/// Resolves in the following states:
|
/// Resolves in the following states:
|
||||||
/// * [MaterialState.pressed].
|
/// * [MaterialState.pressed].
|
||||||
|
@ -162,8 +162,14 @@ class RadioListTile<T> extends StatelessWidget {
|
|||||||
required this.value,
|
required this.value,
|
||||||
required this.groupValue,
|
required this.groupValue,
|
||||||
required this.onChanged,
|
required this.onChanged,
|
||||||
|
this.mouseCursor,
|
||||||
this.toggleable = false,
|
this.toggleable = false,
|
||||||
this.activeColor,
|
this.activeColor,
|
||||||
|
this.fillColor,
|
||||||
|
this.hoverColor,
|
||||||
|
this.overlayColor,
|
||||||
|
this.splashRadius,
|
||||||
|
this.materialTapTargetSize,
|
||||||
this.title,
|
this.title,
|
||||||
this.subtitle,
|
this.subtitle,
|
||||||
this.isThreeLine = false,
|
this.isThreeLine = false,
|
||||||
@ -220,6 +226,20 @@ class RadioListTile<T> extends StatelessWidget {
|
|||||||
/// ```
|
/// ```
|
||||||
final ValueChanged<T?>? onChanged;
|
final ValueChanged<T?>? onChanged;
|
||||||
|
|
||||||
|
/// The cursor for a mouse pointer when it enters or is hovering over the
|
||||||
|
/// widget.
|
||||||
|
///
|
||||||
|
/// If [mouseCursor] is a [MaterialStateProperty<MouseCursor>],
|
||||||
|
/// [MaterialStateProperty.resolve] is used for the following [MaterialState]s:
|
||||||
|
///
|
||||||
|
/// * [MaterialState.selected].
|
||||||
|
/// * [MaterialState.hovered].
|
||||||
|
/// * [MaterialState.disabled].
|
||||||
|
///
|
||||||
|
/// If null, then the value of [RadioThemeData.mouseCursor] is used.
|
||||||
|
/// If that is also null, then [MaterialStateMouseCursor.clickable] is used.
|
||||||
|
final MouseCursor? mouseCursor;
|
||||||
|
|
||||||
/// Set to true if this radio list tile is allowed to be returned to an
|
/// Set to true if this radio list tile is allowed to be returned to an
|
||||||
/// indeterminate state by selecting it again when selected.
|
/// indeterminate state by selecting it again when selected.
|
||||||
///
|
///
|
||||||
@ -250,6 +270,45 @@ class RadioListTile<T> extends StatelessWidget {
|
|||||||
/// Defaults to [ColorScheme.secondary] of the current [Theme].
|
/// Defaults to [ColorScheme.secondary] of the current [Theme].
|
||||||
final Color? activeColor;
|
final Color? activeColor;
|
||||||
|
|
||||||
|
/// The color that fills the radio button.
|
||||||
|
///
|
||||||
|
/// Resolves in the following states:
|
||||||
|
/// * [MaterialState.selected].
|
||||||
|
/// * [MaterialState.hovered].
|
||||||
|
/// * [MaterialState.disabled].
|
||||||
|
///
|
||||||
|
/// If null, then the value of [activeColor] is used in the selected state. If
|
||||||
|
/// that is also null, then the value of [RadioThemeData.fillColor] is used.
|
||||||
|
/// If that is also null, then the default value is used.
|
||||||
|
final MaterialStateProperty<Color?>? fillColor;
|
||||||
|
|
||||||
|
/// {@macro flutter.material.radio.materialTapTargetSize}
|
||||||
|
///
|
||||||
|
/// Defaults to [MaterialTapTargetSize.shrinkWrap].
|
||||||
|
final MaterialTapTargetSize? materialTapTargetSize;
|
||||||
|
|
||||||
|
/// {@macro flutter.material.radio.hoverColor}
|
||||||
|
final Color? hoverColor;
|
||||||
|
|
||||||
|
/// The color for the radio's [Material].
|
||||||
|
///
|
||||||
|
/// Resolves in the following states:
|
||||||
|
/// * [MaterialState.pressed].
|
||||||
|
/// * [MaterialState.selected].
|
||||||
|
/// * [MaterialState.hovered].
|
||||||
|
///
|
||||||
|
/// If null, then the value of [activeColor] with alpha [kRadialReactionAlpha]
|
||||||
|
/// and [hoverColor] is used in the pressed and hovered state. If that is also
|
||||||
|
/// null, the value of [SwitchThemeData.overlayColor] is used. If that is
|
||||||
|
/// also null, then the default value is used in the pressed and hovered state.
|
||||||
|
final MaterialStateProperty<Color?>? overlayColor;
|
||||||
|
|
||||||
|
/// {@macro flutter.material.radio.splashRadius}
|
||||||
|
///
|
||||||
|
/// If null, then the value of [RadioThemeData.splashRadius] is used. If that
|
||||||
|
/// is also null, then [kRadialReactionRadius] is used.
|
||||||
|
final double? splashRadius;
|
||||||
|
|
||||||
/// The primary content of the list tile.
|
/// The primary content of the list tile.
|
||||||
///
|
///
|
||||||
/// Typically a [Text] widget.
|
/// Typically a [Text] widget.
|
||||||
@ -341,8 +400,13 @@ class RadioListTile<T> extends StatelessWidget {
|
|||||||
onChanged: onChanged,
|
onChanged: onChanged,
|
||||||
toggleable: toggleable,
|
toggleable: toggleable,
|
||||||
activeColor: activeColor,
|
activeColor: activeColor,
|
||||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
materialTapTargetSize: materialTapTargetSize ?? MaterialTapTargetSize.shrinkWrap,
|
||||||
autofocus: autofocus,
|
autofocus: autofocus,
|
||||||
|
fillColor: fillColor,
|
||||||
|
mouseCursor: mouseCursor,
|
||||||
|
hoverColor: hoverColor,
|
||||||
|
overlayColor: overlayColor,
|
||||||
|
splashRadius: splashRadius,
|
||||||
);
|
);
|
||||||
Widget? leading, trailing;
|
Widget? leading, trailing;
|
||||||
switch (controlAffinity) {
|
switch (controlAffinity) {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
@ -823,6 +824,423 @@ void main() {
|
|||||||
expect(node.hasFocus, isFalse);
|
expect(node.hasFocus, isFalse);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('Radio changes mouse cursor when hovered', (WidgetTester tester) async {
|
||||||
|
// Test Radio() constructor
|
||||||
|
await tester.pumpWidget(
|
||||||
|
wrap(child: MouseRegion(
|
||||||
|
cursor: SystemMouseCursors.forbidden,
|
||||||
|
child: RadioListTile<int>(
|
||||||
|
mouseCursor: SystemMouseCursors.text,
|
||||||
|
value: 1,
|
||||||
|
onChanged: (int? v) {},
|
||||||
|
groupValue: 2,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
|
||||||
|
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse, pointer: 1);
|
||||||
|
await gesture.addPointer(location: tester.getCenter(find.byType(Radio<int>)));
|
||||||
|
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text);
|
||||||
|
|
||||||
|
|
||||||
|
// Test default cursor
|
||||||
|
await tester.pumpWidget(
|
||||||
|
wrap(child: MouseRegion(
|
||||||
|
cursor: SystemMouseCursors.forbidden,
|
||||||
|
child: RadioListTile<int>(
|
||||||
|
value: 1,
|
||||||
|
onChanged: (int? v) {},
|
||||||
|
groupValue: 2,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click);
|
||||||
|
|
||||||
|
// Test default cursor when disabled
|
||||||
|
await tester.pumpWidget(wrap(
|
||||||
|
child: const MouseRegion(
|
||||||
|
cursor: SystemMouseCursors.forbidden,
|
||||||
|
child: RadioListTile<int>(
|
||||||
|
value: 1,
|
||||||
|
onChanged: null,
|
||||||
|
groupValue: 2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),);
|
||||||
|
|
||||||
|
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('RadioListTile respects fillColor in enabled/disabled states', (WidgetTester tester) async {
|
||||||
|
const Color activeEnabledFillColor = Color(0xFF000001);
|
||||||
|
const Color activeDisabledFillColor = Color(0xFF000002);
|
||||||
|
const Color inactiveEnabledFillColor = Color(0xFF000003);
|
||||||
|
const Color inactiveDisabledFillColor = Color(0xFF000004);
|
||||||
|
|
||||||
|
Color getFillColor(Set<MaterialState> states) {
|
||||||
|
if (states.contains(MaterialState.disabled)) {
|
||||||
|
if (states.contains(MaterialState.selected)) {
|
||||||
|
return activeDisabledFillColor;
|
||||||
|
}
|
||||||
|
return inactiveDisabledFillColor;
|
||||||
|
}
|
||||||
|
if (states.contains(MaterialState.selected)) {
|
||||||
|
return activeEnabledFillColor;
|
||||||
|
}
|
||||||
|
return inactiveEnabledFillColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
final MaterialStateProperty<Color> fillColor =
|
||||||
|
MaterialStateColor.resolveWith(getFillColor);
|
||||||
|
|
||||||
|
int? groupValue = 0;
|
||||||
|
Widget buildApp({required bool enabled}) {
|
||||||
|
return wrap(
|
||||||
|
child: StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
|
||||||
|
return RadioListTile<int>(
|
||||||
|
value: 0,
|
||||||
|
fillColor: fillColor,
|
||||||
|
onChanged: enabled ? (int? newValue) {
|
||||||
|
setState(() {
|
||||||
|
groupValue = newValue;
|
||||||
|
});
|
||||||
|
} : null,
|
||||||
|
groupValue: groupValue,
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildApp(enabled: true));
|
||||||
|
|
||||||
|
// Selected and enabled.
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
Material.of(tester.element(find.byType(Radio<int>))),
|
||||||
|
paints
|
||||||
|
..rect()
|
||||||
|
..circle(color: activeEnabledFillColor)
|
||||||
|
..circle(color: activeEnabledFillColor),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check when the radio isn't selected.
|
||||||
|
groupValue = 1;
|
||||||
|
await tester.pumpWidget(buildApp(enabled: true));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
Material.of(tester.element(find.byType(Radio<int>))),
|
||||||
|
paints
|
||||||
|
..rect()
|
||||||
|
..circle(color: inactiveEnabledFillColor, style: PaintingStyle.stroke, strokeWidth: 2.0),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check when the radio is selected, but disabled.
|
||||||
|
groupValue = 0;
|
||||||
|
await tester.pumpWidget(buildApp(enabled: false));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
Material.of(tester.element(find.byType(Radio<int>))),
|
||||||
|
paints
|
||||||
|
..rect()
|
||||||
|
..circle(color: activeDisabledFillColor)
|
||||||
|
..circle(color: activeDisabledFillColor),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check when the radio is unselected and disabled.
|
||||||
|
groupValue = 1;
|
||||||
|
await tester.pumpWidget(buildApp(enabled: false));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
Material.of(tester.element(find.byType(Radio<int>))),
|
||||||
|
paints
|
||||||
|
..rect()
|
||||||
|
..circle(color: inactiveDisabledFillColor, style: PaintingStyle.stroke, strokeWidth: 2.0),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('RadioListTile respects fillColor in hovered state', (WidgetTester tester) async {
|
||||||
|
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
|
||||||
|
const Color hoveredFillColor = Color(0xFF000001);
|
||||||
|
|
||||||
|
Color getFillColor(Set<MaterialState> states) {
|
||||||
|
if (states.contains(MaterialState.hovered)) {
|
||||||
|
return hoveredFillColor;
|
||||||
|
}
|
||||||
|
return Colors.transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
final MaterialStateProperty<Color> fillColor =
|
||||||
|
MaterialStateColor.resolveWith(getFillColor);
|
||||||
|
|
||||||
|
int? groupValue = 0;
|
||||||
|
Widget buildApp() {
|
||||||
|
return wrap(
|
||||||
|
child: StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
|
||||||
|
return RadioListTile<int>(
|
||||||
|
value: 0,
|
||||||
|
fillColor: fillColor,
|
||||||
|
onChanged: (int? newValue) {
|
||||||
|
setState(() {
|
||||||
|
groupValue = newValue;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
groupValue: groupValue,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildApp());
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// Start hovering
|
||||||
|
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
|
||||||
|
await gesture.addPointer();
|
||||||
|
await gesture.moveTo(tester.getCenter(find.byType(Radio<int>)));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Material.of(tester.element(find.byType(Radio<int>))),
|
||||||
|
paints
|
||||||
|
..rect()..circle()
|
||||||
|
..circle(color: hoveredFillColor),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('RadioListTile respects hoverColor', (WidgetTester tester) async {
|
||||||
|
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
|
||||||
|
int? groupValue = 0;
|
||||||
|
final Color? hoverColor = Colors.orange[500];
|
||||||
|
Widget buildApp({bool enabled = true}) {
|
||||||
|
return wrap(
|
||||||
|
child: StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
|
||||||
|
return RadioListTile<int>(
|
||||||
|
value: 0,
|
||||||
|
onChanged: enabled ? (int? newValue) {
|
||||||
|
setState(() {
|
||||||
|
groupValue = newValue;
|
||||||
|
});
|
||||||
|
} : null,
|
||||||
|
hoverColor: hoverColor,
|
||||||
|
groupValue: groupValue,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await tester.pumpWidget(buildApp());
|
||||||
|
|
||||||
|
await tester.pump();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
Material.of(tester.element(find.byType(Radio<int>))),
|
||||||
|
paints
|
||||||
|
..rect()
|
||||||
|
..circle(color: const Color(0xff2196f3))
|
||||||
|
..circle(color: const Color(0xff2196f3)),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Start hovering
|
||||||
|
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
|
||||||
|
await gesture.moveTo(tester.getCenter(find.byType(Radio<int>)));
|
||||||
|
|
||||||
|
// Check when the radio isn't selected.
|
||||||
|
groupValue = 1;
|
||||||
|
await tester.pumpWidget(buildApp());
|
||||||
|
await tester.pump();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
Material.of(tester.element(find.byType(Radio<int>))),
|
||||||
|
paints
|
||||||
|
..rect()
|
||||||
|
..circle(color: hoverColor)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check when the radio is selected, but disabled.
|
||||||
|
groupValue = 0;
|
||||||
|
await tester.pumpWidget(buildApp(enabled: false));
|
||||||
|
await tester.pump();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
Material.of(tester.element(find.byType(Radio<int>))),
|
||||||
|
paints
|
||||||
|
..rect()
|
||||||
|
..circle(color: const Color(0x61000000))
|
||||||
|
..circle(color: const Color(0x61000000)),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('RadioListTile respects overlayColor in active/pressed/hovered states', (WidgetTester tester) async {
|
||||||
|
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
|
||||||
|
|
||||||
|
const Color fillColor = Color(0xFF000000);
|
||||||
|
const Color activePressedOverlayColor = Color(0xFF000001);
|
||||||
|
const Color inactivePressedOverlayColor = Color(0xFF000002);
|
||||||
|
const Color hoverOverlayColor = Color(0xFF000003);
|
||||||
|
const Color hoverColor = Color(0xFF000005);
|
||||||
|
|
||||||
|
Color? getOverlayColor(Set<MaterialState> states) {
|
||||||
|
if (states.contains(MaterialState.pressed)) {
|
||||||
|
if (states.contains(MaterialState.selected)) {
|
||||||
|
return activePressedOverlayColor;
|
||||||
|
}
|
||||||
|
return inactivePressedOverlayColor;
|
||||||
|
}
|
||||||
|
if (states.contains(MaterialState.hovered)) {
|
||||||
|
return hoverOverlayColor;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildRadio({bool active = false, bool useOverlay = true}) {
|
||||||
|
return wrap(
|
||||||
|
child: RadioListTile<bool>(
|
||||||
|
value: active,
|
||||||
|
groupValue: true,
|
||||||
|
onChanged: (_) { },
|
||||||
|
fillColor: const MaterialStatePropertyAll<Color>(fillColor),
|
||||||
|
overlayColor: useOverlay ? MaterialStateProperty.resolveWith(getOverlayColor) : null,
|
||||||
|
hoverColor: hoverColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildRadio(useOverlay: false));
|
||||||
|
await tester.press(find.byType(Radio<bool>));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Material.of(tester.element(find.byType(Radio<bool>))),
|
||||||
|
paints..circle()
|
||||||
|
..circle(
|
||||||
|
color: fillColor.withAlpha(kRadialReactionAlpha),
|
||||||
|
radius: 20,
|
||||||
|
),
|
||||||
|
reason: 'Default inactive pressed Radio should have overlay color from fillColor',
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildRadio(active: true, useOverlay: false));
|
||||||
|
await tester.press(find.byType(Radio<bool>));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Material.of(tester.element(find.byType(Radio<bool>))),
|
||||||
|
paints..circle()
|
||||||
|
..circle(
|
||||||
|
color: fillColor.withAlpha(kRadialReactionAlpha),
|
||||||
|
radius: 20,
|
||||||
|
),
|
||||||
|
reason: 'Default active pressed Radio should have overlay color from fillColor',
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildRadio());
|
||||||
|
await tester.press(find.byType(Radio<bool>));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Material.of(tester.element(find.byType(Radio<bool>))),
|
||||||
|
paints..circle()
|
||||||
|
..circle(
|
||||||
|
color: inactivePressedOverlayColor,
|
||||||
|
radius: 20,
|
||||||
|
),
|
||||||
|
reason: 'Inactive pressed Radio should have overlay color: $inactivePressedOverlayColor',
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildRadio(active: true));
|
||||||
|
await tester.press(find.byType(Radio<bool>));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Material.of(tester.element(find.byType(Radio<bool>))),
|
||||||
|
paints..circle()
|
||||||
|
..circle(
|
||||||
|
color: activePressedOverlayColor,
|
||||||
|
radius: 20,
|
||||||
|
),
|
||||||
|
reason: 'Active pressed Radio should have overlay color: $activePressedOverlayColor',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Start hovering
|
||||||
|
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
|
||||||
|
await gesture.addPointer();
|
||||||
|
await gesture.moveTo(tester.getCenter(find.byType(Radio<bool>)));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
await tester.pumpWidget(Container());
|
||||||
|
await tester.pumpWidget(buildRadio());
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Material.of(tester.element(find.byType(Radio<bool>))),
|
||||||
|
paints
|
||||||
|
..circle(
|
||||||
|
color: hoverOverlayColor,
|
||||||
|
radius: 20,
|
||||||
|
),
|
||||||
|
reason: 'Hovered Radio should use overlay color $hoverOverlayColor over $hoverColor',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('RadioListTile respects splashRadius', (WidgetTester tester) async {
|
||||||
|
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
|
||||||
|
const double splashRadius = 30;
|
||||||
|
Widget buildApp() {
|
||||||
|
return wrap(
|
||||||
|
child: StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
|
||||||
|
return RadioListTile<int>(
|
||||||
|
value: 0,
|
||||||
|
onChanged: (_) {},
|
||||||
|
hoverColor: Colors.orange[500],
|
||||||
|
groupValue: 0,
|
||||||
|
splashRadius: splashRadius,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await tester.pumpWidget(buildApp());
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
|
||||||
|
await gesture.addPointer();
|
||||||
|
await gesture.moveTo(tester.getCenter(find.byType(Radio<int>)));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
Material.of(tester.element(
|
||||||
|
find.byWidgetPredicate((Widget widget) => widget is Radio<int>),
|
||||||
|
)),
|
||||||
|
paints..circle(color: Colors.orange[500], radius: splashRadius),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Radio respects materialTapTargetSize', (WidgetTester tester) async {
|
||||||
|
await tester.pumpWidget(
|
||||||
|
wrap(child: RadioListTile<bool>(
|
||||||
|
groupValue: true,
|
||||||
|
value: true,
|
||||||
|
onChanged: (bool? newValue) { },
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
|
||||||
|
// default test
|
||||||
|
expect(tester.getSize(find.byType(Radio<bool>)), const Size(40.0, 40.0));
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
wrap(child: RadioListTile<bool>(
|
||||||
|
materialTapTargetSize: MaterialTapTargetSize.padded,
|
||||||
|
groupValue: true,
|
||||||
|
value: true,
|
||||||
|
onChanged: (bool? newValue) { },
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tester.getSize(find.byType(Radio<bool>)), const Size(48.0, 48.0));
|
||||||
|
});
|
||||||
|
|
||||||
group('feedback', () {
|
group('feedback', () {
|
||||||
late FeedbackTester feedback;
|
late FeedbackTester feedback;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user