Unverified Commit b9e3aef2 authored by Taha Tesser's avatar Taha Tesser Committed by GitHub

Add `FocusNode`, `onFocusChange`, and `autofocus` to `CupertinoSwitch` (#126684)

fixes https://github.com/flutter/flutter/issues/126679 

### Description
Control cupertino widgets like `CupertinoCheckbox` and `CupertinoRadio` have `focusNode` and `autofocus`, while these are missing in `CupertinoSwitch`.

This is blocking https://github.com/flutter/flutter/issues/126637 
(`switch.dart` currently maintains its focus node for `CupertinoSwitch` when using `Switch.adaptive` which causes a bug)
parent 6ffcc9e5
......@@ -75,6 +75,9 @@ class CupertinoSwitch extends StatefulWidget {
this.thumbColor,
this.applyTheme,
this.focusColor,
this.focusNode,
this.onFocusChange,
this.autofocus = false,
this.dragStartBehavior = DragStartBehavior.start,
});
......@@ -130,6 +133,15 @@ class CupertinoSwitch extends StatefulWidget {
/// Defaults to a slightly transparent [activeColor].
final Color? focusColor;
/// {@macro flutter.widgets.Focus.focusNode}
final FocusNode? focusNode;
/// {@macro flutter.material.inkwell.onFocusChange}
final ValueChanged<bool>? onFocusChange;
/// {@macro flutter.widgets.Focus.autofocus}
final bool autofocus;
/// {@template flutter.cupertino.CupertinoSwitch.applyTheme}
/// Whether to apply the ambient [CupertinoThemeData].
///
......@@ -356,6 +368,9 @@ class _CupertinoSwitchState extends State<CupertinoSwitch> with TickerProviderSt
onShowFocusHighlight: _onShowFocusHighlight,
actions: _actionMap,
enabled: isInteractive,
focusNode: widget.focusNode,
onFocusChange: widget.onFocusChange,
autofocus: widget.autofocus,
child: _CupertinoSwitchRenderObjectWidget(
value: widget.value,
activeColor: activeColor,
......
......@@ -913,4 +913,115 @@ void main() {
kIsWeb ? SystemMouseCursors.click : SystemMouseCursors.basic,
);
});
testWidgets('CupertinoSwitch is focusable and has correct focus color', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(debugLabel: 'CupertinoSwitch');
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
bool value = true;
const Color focusColor = Color(0xffff0000);
Widget buildApp({bool enabled = true}) {
return Directionality(
textDirection: TextDirection.ltr,
child: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Center(
child: CupertinoSwitch(
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)),
);
});
testWidgets('CupertinoSwitch.onFocusChange callback', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(debugLabel: 'CupertinoSwitch');
bool focused = false;
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Center(
child: CupertinoSwitch(
value: true,
focusNode: focusNode,
onFocusChange: (bool value) {
focused = value;
},
onChanged:(bool newValue) {},
),
),
),
);
focusNode.requestFocus();
await tester.pump();
expect(focused, isTrue);
expect(focusNode.hasFocus, isTrue);
focusNode.unfocus();
await tester.pump();
expect(focused, isFalse);
expect(focusNode.hasFocus, isFalse);
});
}
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