@@ -1016,8 +1016,7 @@ void main() {
1016
1016
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy .alwaysTraditional;
1017
1017
int ? groupValue = 0 ;
1018
1018
final Color ? hoverColor = Colors .orange[500 ];
1019
- final ThemeData theme = ThemeData ();
1020
- final bool material3 = theme.useMaterial3;
1019
+ final ThemeData theme = ThemeData (useMaterial3: true );
1021
1020
Widget buildApp ({bool enabled = true }) {
1022
1021
return wrap (
1023
1022
child: MaterialApp (
@@ -1045,8 +1044,8 @@ void main() {
1045
1044
Material .of (tester.element (find.byType (Radio <int >))),
1046
1045
paints
1047
1046
..rect ()
1048
- ..circle (color: material3 ? theme.colorScheme.primary : const Color ( 0xff2196f3 ) )
1049
- ..circle (color: material3 ? theme.colorScheme.primary : const Color ( 0xff2196f3 ) ),
1047
+ ..circle (color: theme.colorScheme.primary)
1048
+ ..circle (color: theme.colorScheme.primary),
1050
1049
);
1051
1050
1052
1051
// Start hovering
@@ -1074,8 +1073,8 @@ void main() {
1074
1073
Material .of (tester.element (find.byType (Radio <int >))),
1075
1074
paints
1076
1075
..rect ()
1077
- ..circle (color: material3 ? theme.colorScheme.onSurface.withOpacity (0.38 ) : const Color ( 0x61000000 ))
1078
- ..circle (color: material3 ? theme.colorScheme.onSurface.withOpacity (0.38 ) : const Color ( 0x61000000 )),
1076
+ ..circle (color: theme.colorScheme.onSurface.withOpacity (0.38 ))
1077
+ ..circle (color: theme.colorScheme.onSurface.withOpacity (0.38 )),
1079
1078
);
1080
1079
});
1081
1080
@@ -1101,13 +1100,11 @@ void main() {
1101
1100
return null ;
1102
1101
}
1103
1102
1104
- final ThemeData theme = ThemeData (useMaterial3: false );
1105
- final bool material3 = theme.useMaterial3;
1106
1103
Widget buildRadio ({bool active = false , bool useOverlay = true }) {
1107
- return wrap (
1108
- child : MaterialApp (
1109
- theme : theme,
1110
- home : RadioListTile <bool >(
1104
+ return MaterialApp (
1105
+ theme : ThemeData (useMaterial3 : true ),
1106
+ home : Material (
1107
+ child : RadioListTile <bool >(
1111
1108
value: active,
1112
1109
groupValue: true ,
1113
1110
onChanged: (_) { },
@@ -1125,13 +1122,13 @@ void main() {
1125
1122
1126
1123
expect (
1127
1124
Material .of (tester.element (find.byType (Radio <bool >))),
1128
- material3 ? ( paints.. circle (
1129
- color: fillColor. withAlpha (kRadialReactionAlpha),
1130
- radius : 20 ,
1131
- )) : (paints.. circle () ..circle (
1132
- color: fillColor.withAlpha (kRadialReactionAlpha),
1133
- radius: 20 ,
1134
- ) ),
1125
+ paints
1126
+ .. rect ( color: const Color ( 0x00000000 ))
1127
+ .. rect (color : const Color ( 0x66bcbcbc ))
1128
+ ..circle (
1129
+ color: fillColor.withAlpha (kRadialReactionAlpha),
1130
+ radius: 20.0 ,
1131
+ ),
1135
1132
reason: 'Default inactive pressed Radio should have overlay color from fillColor' ,
1136
1133
);
1137
1134
@@ -1141,13 +1138,13 @@ void main() {
1141
1138
1142
1139
expect (
1143
1140
Material .of (tester.element (find.byType (Radio <bool >))),
1144
- material3 ? ( paints.. circle (
1145
- color: fillColor. withAlpha (kRadialReactionAlpha),
1146
- radius : 20 ,
1147
- )) : (paints.. circle () ..circle (
1148
- color: fillColor.withAlpha (kRadialReactionAlpha),
1149
- radius: 20 ,
1150
- ) ),
1141
+ paints
1142
+ .. rect ( color: const Color ( 0x00000000 ))
1143
+ .. rect (color : const Color ( 0x66bcbcbc ))
1144
+ ..circle (
1145
+ color: fillColor.withAlpha (kRadialReactionAlpha),
1146
+ radius: 20.0 ,
1147
+ ),
1151
1148
reason: 'Default active pressed Radio should have overlay color from fillColor' ,
1152
1149
);
1153
1150
@@ -1157,13 +1154,13 @@ void main() {
1157
1154
1158
1155
expect (
1159
1156
Material .of (tester.element (find.byType (Radio <bool >))),
1160
- material3 ? ( paints.. circle (
1161
- color: inactivePressedOverlayColor,
1162
- radius : 20 ,
1163
- )) : (paints.. circle () ..circle (
1164
- color: inactivePressedOverlayColor,
1165
- radius: 20 ,
1166
- ) ),
1157
+ paints
1158
+ .. rect ( color: const Color ( 0x00000000 ))
1159
+ .. rect (color : const Color ( 0x66bcbcbc ))
1160
+ ..circle (
1161
+ color: inactivePressedOverlayColor,
1162
+ radius: 20.0 ,
1163
+ ),
1167
1164
reason: 'Inactive pressed Radio should have overlay color: $inactivePressedOverlayColor ' ,
1168
1165
);
1169
1166
@@ -1173,17 +1170,17 @@ void main() {
1173
1170
1174
1171
expect (
1175
1172
Material .of (tester.element (find.byType (Radio <bool >))),
1176
- material3 ? ( paints.. circle (
1177
- color: activePressedOverlayColor,
1178
- radius : 20 ,
1179
- )) : (paints.. circle () ..circle (
1180
- color: activePressedOverlayColor,
1181
- radius: 20 ,
1182
- ) ),
1173
+ paints
1174
+ .. rect ( color: const Color ( 0x00000000 ))
1175
+ .. rect (color : const Color ( 0x66bcbcbc ))
1176
+ ..circle (
1177
+ color: activePressedOverlayColor,
1178
+ radius: 20.0 ,
1179
+ ),
1183
1180
reason: 'Active pressed Radio should have overlay color: $activePressedOverlayColor ' ,
1184
1181
);
1185
1182
1186
- // Start hovering
1183
+ // Start hovering.
1187
1184
final TestGesture gesture = await tester.createGesture (kind: PointerDeviceKind .mouse);
1188
1185
await gesture.addPointer ();
1189
1186
await gesture.moveTo (tester.getCenter (find.byType (Radio <bool >)));
@@ -1195,13 +1192,13 @@ void main() {
1195
1192
1196
1193
expect (
1197
1194
Material .of (tester.element (find.byType (Radio <bool >))),
1198
- material3 ? ( paints.. circle (
1199
- color: hoverOverlayColor,
1200
- radius : 20 ,
1201
- )) : (paints ..circle (
1202
- color: hoverOverlayColor,
1203
- radius: 20 ,
1204
- ) ),
1195
+ paints
1196
+ .. rect ( color: const Color ( 0x00000000 ))
1197
+ .. rect (color : const Color ( 0x0a000000 ))
1198
+ ..circle (
1199
+ color: hoverOverlayColor,
1200
+ radius: 20.0 ,
1201
+ ),
1205
1202
reason: 'Hovered Radio should use overlay color $hoverOverlayColor over $hoverColor ' ,
1206
1203
);
1207
1204
});
@@ -1336,4 +1333,179 @@ void main() {
1336
1333
expect (feedback.hapticCount, 0 );
1337
1334
});
1338
1335
});
1336
+
1337
+ group ('Material 2' , () {
1338
+ // These tests are only relevant for Material 2. Once Material 2
1339
+ // support is deprecated and the APIs are removed, these tests
1340
+ // can be deleted.
1341
+
1342
+ testWidgets ('RadioListTile respects overlayColor in active/pressed/hovered states' , (WidgetTester tester) async {
1343
+ tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy .alwaysTraditional;
1344
+
1345
+ const Color fillColor = Color (0xFF000000 );
1346
+ const Color activePressedOverlayColor = Color (0xFF000001 );
1347
+ const Color inactivePressedOverlayColor = Color (0xFF000002 );
1348
+ const Color hoverOverlayColor = Color (0xFF000003 );
1349
+ const Color hoverColor = Color (0xFF000005 );
1350
+
1351
+ Color ? getOverlayColor (Set <MaterialState > states) {
1352
+ if (states.contains (MaterialState .pressed)) {
1353
+ if (states.contains (MaterialState .selected)) {
1354
+ return activePressedOverlayColor;
1355
+ }
1356
+ return inactivePressedOverlayColor;
1357
+ }
1358
+ if (states.contains (MaterialState .hovered)) {
1359
+ return hoverOverlayColor;
1360
+ }
1361
+ return null ;
1362
+ }
1363
+
1364
+ Widget buildRadio ({bool active = false , bool useOverlay = true }) {
1365
+ return MaterialApp (
1366
+ theme: ThemeData (useMaterial3: false ),
1367
+ home: Material (
1368
+ child: RadioListTile <bool >(
1369
+ value: active,
1370
+ groupValue: true ,
1371
+ onChanged: (_) { },
1372
+ fillColor: const MaterialStatePropertyAll <Color >(fillColor),
1373
+ overlayColor: useOverlay ? MaterialStateProperty .resolveWith (getOverlayColor) : null ,
1374
+ hoverColor: hoverColor,
1375
+ ),
1376
+ ),
1377
+ );
1378
+ }
1379
+
1380
+ await tester.pumpWidget (buildRadio (useOverlay: false ));
1381
+ await tester.press (find.byType (Radio <bool >));
1382
+ await tester.pumpAndSettle ();
1383
+
1384
+ expect (
1385
+ Material .of (tester.element (find.byType (Radio <bool >))),
1386
+ paints
1387
+ ..circle ()
1388
+ ..circle (
1389
+ color: fillColor.withAlpha (kRadialReactionAlpha),
1390
+ radius: 20 ,
1391
+ ),
1392
+ reason: 'Default inactive pressed Radio should have overlay color from fillColor' ,
1393
+ );
1394
+
1395
+ await tester.pumpWidget (buildRadio (active: true , useOverlay: false ));
1396
+ await tester.press (find.byType (Radio <bool >));
1397
+ await tester.pumpAndSettle ();
1398
+
1399
+ expect (
1400
+ Material .of (tester.element (find.byType (Radio <bool >))),
1401
+ paints
1402
+ ..circle ()
1403
+ ..circle (
1404
+ color: fillColor.withAlpha (kRadialReactionAlpha),
1405
+ radius: 20 ,
1406
+ ),
1407
+ reason: 'Default active pressed Radio should have overlay color from fillColor' ,
1408
+ );
1409
+
1410
+ await tester.pumpWidget (buildRadio ());
1411
+ await tester.press (find.byType (Radio <bool >));
1412
+ await tester.pumpAndSettle ();
1413
+
1414
+ expect (
1415
+ Material .of (tester.element (find.byType (Radio <bool >))),
1416
+ paints
1417
+ ..circle ()
1418
+ ..circle (
1419
+ color: inactivePressedOverlayColor,
1420
+ radius: 20 ,
1421
+ ),
1422
+ reason: 'Inactive pressed Radio should have overlay color: $inactivePressedOverlayColor ' ,
1423
+ );
1424
+
1425
+ // Start hovering.
1426
+ final TestGesture gesture = await tester.createGesture (kind: PointerDeviceKind .mouse);
1427
+ await gesture.addPointer ();
1428
+ await gesture.moveTo (tester.getCenter (find.byType (Radio <bool >)));
1429
+ await tester.pumpAndSettle ();
1430
+
1431
+ await tester.pumpWidget (Container ());
1432
+ await tester.pumpWidget (buildRadio ());
1433
+ await tester.pumpAndSettle ();
1434
+
1435
+ expect (
1436
+ Material .of (tester.element (find.byType (Radio <bool >))),
1437
+ paints
1438
+ ..circle (
1439
+ color: hoverOverlayColor,
1440
+ radius: 20 ,
1441
+ ),
1442
+ reason: 'Hovered Radio should use overlay color $hoverOverlayColor over $hoverColor ' ,
1443
+ );
1444
+ });
1445
+
1446
+ testWidgets ('RadioListTile respects hoverColor' , (WidgetTester tester) async {
1447
+ tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy .alwaysTraditional;
1448
+ int ? groupValue = 0 ;
1449
+ final Color ? hoverColor = Colors .orange[500 ];
1450
+ Widget buildApp ({bool enabled = true }) {
1451
+ return wrap (
1452
+ child: MaterialApp (
1453
+ theme: ThemeData (useMaterial3: false ),
1454
+ home: StatefulBuilder (builder: (BuildContext context, StateSetter setState) {
1455
+ return RadioListTile <int >(
1456
+ value: 0 ,
1457
+ onChanged: enabled ? (int ? newValue) {
1458
+ setState (() {
1459
+ groupValue = newValue;
1460
+ });
1461
+ } : null ,
1462
+ hoverColor: hoverColor,
1463
+ groupValue: groupValue,
1464
+ );
1465
+ }),
1466
+ ),
1467
+ );
1468
+ }
1469
+ await tester.pumpWidget (buildApp ());
1470
+
1471
+ await tester.pump ();
1472
+ await tester.pumpAndSettle ();
1473
+ expect (
1474
+ Material .of (tester.element (find.byType (Radio <int >))),
1475
+ paints
1476
+ ..rect ()
1477
+ ..circle (color: const Color (0xff2196f3 ))
1478
+ ..circle (color: const Color (0xff2196f3 )),
1479
+ );
1480
+
1481
+ // Start hovering
1482
+ final TestGesture gesture = await tester.createGesture (kind: PointerDeviceKind .mouse);
1483
+ await gesture.moveTo (tester.getCenter (find.byType (Radio <int >)));
1484
+
1485
+ // Check when the radio isn't selected.
1486
+ groupValue = 1 ;
1487
+ await tester.pumpWidget (buildApp ());
1488
+ await tester.pump ();
1489
+ await tester.pumpAndSettle ();
1490
+ expect (
1491
+ Material .of (tester.element (find.byType (Radio <int >))),
1492
+ paints
1493
+ ..rect ()
1494
+ ..circle (color: hoverColor)
1495
+ );
1496
+
1497
+ // Check when the radio is selected, but disabled.
1498
+ groupValue = 0 ;
1499
+ await tester.pumpWidget (buildApp (enabled: false ));
1500
+ await tester.pump ();
1501
+ await tester.pumpAndSettle ();
1502
+ expect (
1503
+ Material .of (tester.element (find.byType (Radio <int >))),
1504
+ paints
1505
+ ..rect ()
1506
+ ..circle (color: const Color (0x61000000 ))
1507
+ ..circle (color: const Color (0x61000000 )),
1508
+ );
1509
+ });
1510
+ });
1339
1511
}
0 commit comments