Skip to content

Commit

Permalink
Fix focus behavior and provided thumb and focus color aren't applied …
Browse files Browse the repository at this point in the history
…to Cupertino variant of `Switch.adaptive` (flutter#126688)

fixes flutter#126637
fixes flutter#126669

##  ~~To be merged after flutter#126684

### Description

1.  Fix the Cupertino variant of `Switch.adaptive` requires two tab key presses to focus.
2.  Fix `thumbColor` & `focusColor` aren't applied.

### Before
Requires two tab presses to focus. and `thumbColor` & `focusColor` aren't applied.

https://github.com/flutter/flutter/assets/48603081/24635551-0794-443f-8320-32fdaa5de57a

### After
Single tab key to focus (no additional focus node) and `thumbColor` & `focusColor` are applied.

https://github.com/flutter/flutter/assets/48603081/9bf42fd8-c7e0-475a-b933-192a94650b0c
  • Loading branch information
TahaTesser authored and Casey Hillers committed May 24, 2023
1 parent 22300e8 commit a7043f9
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 17 deletions.
32 changes: 16 additions & 16 deletions packages/flutter/lib/src/material/switch.dart
Original file line number Diff line number Diff line change
Expand Up @@ -570,22 +570,22 @@ class Switch extends StatelessWidget {

Widget _buildCupertinoSwitch(BuildContext context) {
final Size size = _getSwitchSize(context);
return Focus(
focusNode: focusNode,
onFocusChange: onFocusChange,
autofocus: autofocus,
child: Container(
width: size.width, // Same size as the Material switch.
height: size.height,
alignment: Alignment.center,
child: CupertinoSwitch(
dragStartBehavior: dragStartBehavior,
value: value,
onChanged: onChanged,
activeColor: activeColor,
trackColor: inactiveTrackColor,
applyTheme: applyCupertinoTheme,
),
return Container(
width: size.width, // Same size as the Material switch.
height: size.height,
alignment: Alignment.center,
child: CupertinoSwitch(
dragStartBehavior: dragStartBehavior,
value: value,
onChanged: onChanged,
activeColor: activeColor,
trackColor: inactiveTrackColor,
thumbColor: thumbColor?.resolve(<MaterialState>{}),
applyTheme: applyCupertinoTheme,
focusColor: focusColor,
focusNode: focusNode,
onFocusChange: onFocusChange,
autofocus: autofocus,
),
);
}
Expand Down
94 changes: 93 additions & 1 deletion packages/flutter/test/material/switch_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -791,7 +791,10 @@ void main() {

testWidgets('Switch.adaptive', (WidgetTester tester) async {
bool value = false;
const Color inactiveTrackColor = Colors.pink;
const Color activeTrackColor = Color(0xffff1200);
const Color inactiveTrackColor = Color(0xffff12ff);
const Color thumbColor = Color(0xffffff00);
const Color focusColor = Color(0xff00ff00);

Widget buildFrame(TargetPlatform platform) {
return MaterialApp(
Expand All @@ -802,7 +805,10 @@ void main() {
child: Center(
child: Switch.adaptive(
value: value,
activeColor: activeTrackColor,
inactiveTrackColor: inactiveTrackColor,
thumbColor: const MaterialStatePropertyAll<Color?>(thumbColor),
focusColor: focusColor,
onChanged: (bool newValue) {
setState(() {
value = newValue;
Expand All @@ -822,7 +828,10 @@ void main() {
expect(find.byType(CupertinoSwitch), findsOneWidget, reason: 'on ${platform.name}');

final CupertinoSwitch adaptiveSwitch = tester.widget(find.byType(CupertinoSwitch));
expect(adaptiveSwitch.activeColor, activeTrackColor, reason: 'on ${platform.name}');
expect(adaptiveSwitch.trackColor, inactiveTrackColor, reason: 'on ${platform.name}');
expect(adaptiveSwitch.thumbColor, thumbColor, reason: 'on ${platform.name}');
expect(adaptiveSwitch.focusColor, focusColor, reason: 'on ${platform.name}');

expect(value, isFalse, reason: 'on ${platform.name}');
await tester.tap(find.byType(Switch));
Expand Down Expand Up @@ -3278,6 +3287,89 @@ void main() {
);
});
});

testWidgets('Switch.adaptive(Cupertino) is focusable and has correct focus color', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(debugLabel: 'Switch.adaptive');
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
bool value = true;
const Color focusColor = Color(0xffff0000);

Widget buildApp({bool enabled = true}) {
return MaterialApp(
theme: ThemeData(platform: TargetPlatform.iOS),
home: Material(
child: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Center(
child: Switch.adaptive(
value: value,
onChanged: enabled ? (bool newValue) {
setState(() {
value = newValue;
});
} : null,
focusColor: focusColor,
focusNode: focusNode,
autofocus: true,
),
);
},
),
),
);
}

await tester.pumpWidget(buildApp());
await tester.pumpAndSettle();

expect(focusNode.hasPrimaryFocus, isTrue);
expect(
find.byType(CupertinoSwitch),
paints
..rrect(color: const Color(0xff34c759))
..rrect(color: focusColor)
..clipRRect()
..rrect(color: const Color(0x26000000))
..rrect(color: const Color(0x0f000000))
..rrect(color: const Color(0x0a000000))
..rrect(color: const Color(0xffffffff)),
);

// Check the false value.
value = false;
await tester.pumpWidget(buildApp());
await tester.pumpAndSettle();

expect(focusNode.hasPrimaryFocus, isTrue);
expect(
find.byType(CupertinoSwitch),
paints
..rrect(color: const Color(0x28787880))
..rrect(color: focusColor)
..clipRRect()
..rrect(color: const Color(0x26000000))
..rrect(color: const Color(0x0f000000))
..rrect(color: const Color(0x0a000000))
..rrect(color: const Color(0xffffffff)),
);

// Check what happens when disabled.
value = false;
await tester.pumpWidget(buildApp(enabled: false));
await tester.pumpAndSettle();

expect(focusNode.hasPrimaryFocus, isFalse);
expect(
find.byType(CupertinoSwitch),
paints
..rrect(color: const Color(0x28787880))
..clipRRect()
..rrect(color: const Color(0x26000000))
..rrect(color: const Color(0x0f000000))
..rrect(color: const Color(0x0a000000))
..rrect(color: const Color(0xffffffff)),
);
});
}

class DelayedImageProvider extends ImageProvider<DelayedImageProvider> {
Expand Down

0 comments on commit a7043f9

Please sign in to comment.