Reputation: 3708
I want to focus on the first Button A
of the bottom Hstack
when the user navigates downwards. How can I achieve that?
As of now, the guide is picking the nearest element.
import SwiftUI
struct DummyView: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
contentView
parent
}
private var parent: some View {
VStack {
if #available(tvOS 15.0, *) {
HStack {
Spacer()
Button ("1") {}
Button ("2") {}
Button ("3") {}
Spacer()
}
.focusSection()
.border(Color.white, width: 2)
} else {
// Fallback on earlier versions
}
Spacer()
if #available(tvOS 15.0, *) {
HStack {
Button ("A") {}
Spacer()
Button ("B") {}
Spacer()
Button ("C") {}
}
.border(Color.white, width: 2)
.focusSection()
} else {
// Fallback on earlier versions
}
}
}
private var contentView: some View {
VStack {
Spacer()
Text("THIS IS DUMMY SCREEN")
Spacer()
}
}
}
Upvotes: 1
Views: 1877
Reputation: 101
I've used @FocusState to achieve this. You can bind the focus state of the view to an enum, then create an empty view to intercept/direct focus when it receives focus:
import SwiftUI
struct DummyView: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
contentView
parent
}
enum FocusAreas {
case button1
case button2
case button3
case focusGuide
case buttonA
case buttonB
case buttonC
}
@FocusState var focusState: FocusAreas?
private var parent: some View {
VStack {
if #available(tvOS 15.0, *) {
HStack {
Spacer()
Button ("1") {}
.focused($focusState, equals: .button1)
Button ("2") {}
.focused($focusState, equals: .button2)
Button ("3") {}
.focused($focusState, equals: .button3)
Spacer()
}
.border(Color.white, width: 2)
} else {
// Fallback on earlier versions
}
Color.clear
.frame(height: 1)
.frame(maxWidth: .infinity)
.focusable()
.focused($focusState, equals: .focusGuide)
.onChange(of: focusState, perform: {[focusState] newFocus in
if(newFocus == .focusGuide) {
switch(focusState){
case .button1,.button2,.button3:
self.focusState = .buttonA
default:
//Add custom behaviors when navigating up here from buttons A,B,C here
self.focusState = .button1
break
}
}
})
Spacer()
if #available(tvOS 15.0, *) {
HStack {
Button ("A") {}
.focused($focusState, equals: .buttonA
)
Spacer()
Button ("B") {}
.focused($focusState, equals: .buttonB)
Spacer()
Button ("C") {}
.focused($focusState, equals: .buttonC)
}
.border(Color.white, width: 2)
} else {
// Fallback on earlier versions
}
}
}
private var contentView: some View {
VStack {
Spacer()
Text("THIS IS DUMMY SCREEN")
Spacer()
}
}
}
Upvotes: 2