move focus with focusState swiftUI

40 Views Asked by At

I have a sample code where the focus works the way I need it to. when entering a character, the focus moves to the next textField.

struct CheckField: View {
    @State private var texts = Array(repeating: "", count: 5)
    @ObservedObject private var viewModel = LetterViewModel()
    @FocusState private var focusedField: Int?

    var body: some View {
        LazyVGrid(columns: [GridItem(.adaptive(minimum: 15, maximum: 25))], spacing: 10) {
            ForEach(0..<texts.count, id: \.self) { index in
                CustomTextField(text: $texts[index],
                                expectedCharacter: Character("A"),
                                isCorrectBinding: .constant(false),
                                onTextChanged: { text, isCorrect in
                },
                                viewModel: viewModel)
                .tag(index)
                .focused($focusedField, equals: index)
                .onChange(of: texts[index]) { _ in
                    if texts[index].count == 1 && index < texts.count - 1 {
                        let nextField = index + 1
                        DispatchQueue.main.async {
                            texts[nextField] = ""
                            focusedField = nextField
                        }
                    }
                }
                .onAppear {
                    focusedField = 0
                }
            }
        }
    }
}

but when i try to do the same logic for my code the focus doesn't move after typing. I understand that in the code that is shown as an example - we add a textifeld with the help of forEach, and in the same place we set and adjust the focus. and the code that I will attach below is slightly different. I have a view where there is a loop and the addition of a textField (letterRowView), and the implementation itself is in another view (letterView). if I move letterView to letterRowView, and move the initialized viewModel there - then when entering a character in the first field, it will be displayed in all added textFields. so I need to make the focus as in the example.

I need the focus to be on the first textfield when the screen is displayed. and after entering a character in the first field, the focus moved to the second field, and so on until there are empty textfields. how can you achieve the goal?

Here is my code:

struct LetterView: View {
// MARK: - Properties
var startIndex: Int
@State var index: Int
var blankIndexes: [Int]
@FocusState private var focusedField: Int?
@State var mutableStartIndex: Int = 0    
@State var currentIndex: Int = 0

// MARK: - View body
var body: some View {
    if isBlank {
        CustomTextField(text: $viewModel.enteredText,
                        expectedCharacter: expectedCharacter,
                        isCorrectBinding: $viewModel.isCorrect,
                        onTextChanged: { newText, isCorrect in
                            handleTextChange(newText, isCorrect)
                            userAnswer(newText, isCorrect, index)
                        }, viewModel: viewModel)
            .frame(width: 20, height: 30)
            .background(viewModel.backgroundColor)
            .foregroundColor(viewModel.textColor)
            .tag(index)
            .focused($focusedField, equals: currentIndex)
            .onChange(of: viewModel.isCorrect) { _ in
                if viewModel.isCorrect == true {
                    let nextField = index + 1
                    if nextField < blankIndexes.count {
                        focusedField = nextField
                    }
                }
            }
            .onAppear {
                focusedField = startIndex
                // Assign currentIndex on appear
                currentIndex = index
      }
    } 
  }
}
0

There are 0 best solutions below