Is it possible programmatically move focus to a button? By "focus," I mean the border around an element when Full Keyboard Access is enabled.
For example, in the following code, I expect the focus to move to Button2 when clicking "Move focus to Button2," but it doesn't seem to work:
struct ContentView: View {
@FocusState private var focusedElement: FocusableElement?
enum FocusableElement: Hashable {
case button
}
var body: some View {
VStack{
VStack {
Button("Move focus to Button2") {
focusedElement = .button
}
Button("Button2") {}
.focused($focusedElement, equals: .button)
}
}
}
}
I would expect:
Is it possible programmatically move focus to a button? By "focus," I mean the border around an element when Full Keyboard Access is enabled.
For example, in the following code, I expect the focus to move to Button2 when clicking "Move focus to Button2," but it doesn't seem to work:
struct ContentView: View {
@FocusState private var focusedElement: FocusableElement?
enum FocusableElement: Hashable {
case button
}
var body: some View {
VStack{
VStack {
Button("Move focus to Button2") {
focusedElement = .button
}
Button("Button2") {}
.focused($focusedElement, equals: .button)
}
}
}
}
I would expect:
Share Improve this question asked Mar 10 at 13:41 sashsash 8,7575 gold badges68 silver badges76 bronze badges 1- A button doesn't inherently have "Focus". You need to use accessibility focus for this to work, alternatively you can perform a hack by making the buttons a "TextField" but eww. – xTwisteDx Commented Mar 10 at 14:58
2 Answers
Reset to default 1The focusedElement
seems to change for me on iOS18, tested on real device.
Try this approach using .focusable()
and a .border
to show the button change of focus in red.
struct ContentView: View {
@FocusState private var focusedElement: FocusableElement?
enum FocusableElement: Hashable {
case button
}
var body: some View {
VStack (spacing: 55) {
Button("Move focus to Button2") {
focusedElement = .button
}
.border(focusedElement == .button ? Color.clear : Color.red, width: 4)
Button("Button2") {
focusedElement = nil
}
.focusable()
.focused($focusedElement, equals: .button)
.border(focusedElement == .button ? Color.red : Color.clear, width: 4)
}
}
}
Another example:
struct ContentView: View {
@FocusState private var focusedElement: FocusableElement?
enum FocusableElement: Hashable {
case button1
case button2
}
var body: some View {
VStack (spacing: 55) {
Button("Move focus to Button2") {
focusedElement = .button2
}
.focusable()
.focused($focusedElement, equals: .button1)
.border(focusedElement == .button1 ? Color.red : Color.clear, width: 4)
Button("Move focus to Button1") {
focusedElement = .button1
}
.focusable()
.focused($focusedElement, equals: .button2)
.border(focusedElement == .button2 ? Color.red : Color.clear, width: 4)
}
}
}
In theory you should be able to add an @AccessibilityFocusState enum to your view, and then binding various enum values to different views using the accessibilityFocused
ViewModifier
.
I say "in theory" because as far as I can tell this feature of SwiftUI is broken for Full keyboard access. It just doesn't work.
I posted a thread here on SO when I first started trying to get this to work. I've since talked with other iOS devs who have had the same problem.