RookieIntern
RookieIntern

Reputation: 1

FocusState on Pickers

is there a possible way when we are in the textfield then pressing tab button the picker is automatically selected, by using @FocusState?

i have tried using @FocusState but it seems it only works on textFields, is there other way that it will work on pickers?

struct FormFields: View {
@FocusState private var focusedField: Field?
@ObservedObject var viewModel: AddCustomerViewModel
@Binding var showReference: Bool

enum Field: Hashable {
    case name, classification
}

var body: some View {
    VStack {
        TextField(Labels.name, text: $viewModel.name)
            .focused($focusedField, equals: .name)
            .onSubmit { focusedField = .classification }
        
        Picker(Labels.classification, selection: $viewModel.classification) {
            Text("").tag(nil as CustomerClassification?)
            ForEach(CustomerClassification.allCases, id: \.self) { classification in
                Text(classification.rawValue).tag(classification as CustomerClassification?)
            }
        }
        .focused($focusedField, equals: .classification)
    }
}

Upvotes: 0

Views: 57

Answers (1)

Fahim Parkar
Fahim Parkar

Reputation: 31647

To implement the behavior where pressing the Tab key focuses on a Picker when the TextField is focused (and vice versa), you're on the right track with using @FocusState. But there is a subtle issue, the Picker doesn't automatically take focus in the same way a TextField does.

The challenge is that @FocusState works directly with views that can take focus, such as TextField and TextEditor. For other views like Picker, focus management isn't built-in, but you can still work around this limitation by adjusting the logic around when the Picker should be treated as focused.

To achieve this, we need to use the .onChange modifier to detect when the focusedField changes, and then trigger selection on the Picker.

struct FormFields: View {
    @FocusState private var focusedField: Field?
    @ObservedObject var viewModel: AddCustomerViewModel
    @Binding var showReference: Bool

    enum Field: Hashable {
        case name, classification
    }

    var body: some View {
        VStack {
            TextField(Labels.name, text: $viewModel.name)
                .focused($focusedField, equals: .name)
                .onSubmit {
                    focusedField = .classification // Move to the next field
                }
            
            Picker(Labels.classification, selection: $viewModel.classification) {
                Text("").tag(nil as CustomerClassification?)
                ForEach(CustomerClassification.allCases, id: \.self) { classification in
                    Text(classification.rawValue).tag(classification as CustomerClassification?)
                }
            }
            .focused($focusedField, equals: .classification)
            .onChange(of: focusedField) { newValue in
                if newValue == .classification {
                    // You can add logic here to trigger a default picker selection if necessary
                    // For example, if you want to select a default classification:
                    if viewModel.classification == nil {
                        viewModel.classification = CustomerClassification.allCases.first
                    }
                }
            }
        }
        .onChange(of: focusedField) { newFocus in
            // Handle the change in focus (e.g., when Tab is pressed)
            if newFocus == .name {
                // Logic when the focus is on the name field
            }
            if newFocus == .classification {
                // Logic when the focus is on the classification Picker
            }
        }
    }
}

Upvotes: 0

Related Questions