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
}
}
}
}