Home > Software design >  SwiftUI: How to move/jump to next TextField without hiding keyboard?
SwiftUI: How to move/jump to next TextField without hiding keyboard?

Time:07-28

I'm solving how to move/jump in pure SwiftUI. Below is example code which is not working correctly, but there is an idea of how it should work.

struct ContentView: View {
    @FocusState private var focused: Bool
    @State private var activeIndex: Int = 0

    var body: some View {
        HStack(spacing: 3) {
            ForEach(0..<10, id: \.self) { index in
                Stone(activeIndex: $activeIndex, focused: _focused, index: index)
            }
        }
                .padding(.horizontal)
    }
}

The problem when I'm trying to move/jump to next TextField is, that nothing will happen.

struct Stone: View {
    @Binding var activeIndex: Int
    @FocusState var focused: Bool
    @State var index: Int
    @State private var text: String = ""

    var body: some View {
        GeometryReader { bounds in
            ZStack {
                TextField("", text: $text)
                        .multilineTextAlignment(.center)
                        .focused($focused)
                        .background(index == activeIndex ? .red : .green)
                        .onChange(of: text) { newValue in
                            if let lastValue = newValue.last {
                                text = String(lastValue)

                                activeIndex  = 1

                                focused = true
                            }
                        }
            }
                    .frame(width: bounds.size.width, height: bounds.size.height)
        }
                .scaledToFit()
    }
}

I found some number of ways how to jump/move to next TextField, but mostly in UIKit. So my question is, how can I move/jump to next TextField in pure SwiftUI?

Thanks!

CodePudding user response:

Here is a functional example to understand what I meant by my question.

struct ContentView: View {
    @FocusState private var focusedField: Int?

    var body: some View {
        HStack(spacing: 3) {
            ForEach(0..<10, id: \.self) { index in
                Stone(focusedField: _focusedField, index: index)
            }
        }
                .padding(.horizontal)
    }
}
struct Stone: View {
    @FocusState var focusedField: Int?
    @State var index: Int
    @State private var text: String = ""

    var body: some View {
        TextField("", text: $text)
                .focused($focusedField, equals: index)
                .textFieldStyle(.roundedBorder)
                .onChange(of: text) { newValue in
                    setFocus(index: index)
                }
    }

    func setFocus(index: Int) {
        /// Default to the first box when focus is not set or the user reaches the last box
        if focusedField == nil || focusedField == 9 {
            focusedField = 0
        } else {
            /// Another safety check for the index
            if index == 9 {
                focusedField = 0
            } else {
                focusedField = index   1
            }
        }
    }
}

Thanks to all!

  • Related