SwiftUI:输入 1 个字符后是否可以自动移动到下一个文本字段?

dcv*_*onb 6 textfield swiftui

我试图制作一个 SwiftUI 应用程序,在其中输入一个字母后TextField,光标会自动移动到下一个TextField. 用户界面非常像这样

在 Swift/IB 中,看起来这是通过委托完成的,并在这篇文章中添加了一个目标: 如何在 Swift 中自动移动到下一个 UITextField

但是找不到任何在 SwiftUI 中使用委托/目标的文档。

我尝试关注这篇文章: SwiftUI TextField max length 但这对我不起作用。设置.prefix(1)似乎没有什么区别。在TextField仍然接受任何字符数量,当移动到下一个TextField不降低进入到只有第一个字符的字符。

在SwiftUI的当前状态下,是否可以TextField在输入1个字符后自动移动到下一个?

谢谢你的帮助!

lor*_*sum 3

它可以在 iOS 15 中完成FocusState

import SwiftUI
///Sample usage
@available(iOS 15.0, *)
struct PinParentView: View {
    @State var pin: Int = 12356
    var body: some View {
        VStack{
            Text(pin.description)
            PinView(pin: $pin)
        }
    }
}
@available(iOS 15.0, *)
struct PinView: View {
    @Binding var pin: Int
    @State var pinDict: [UniqueCharacter] = []
    @FocusState private var focusedField: UniqueCharacter?
    var body: some View{
        HStack{
            ForEach($pinDict, id: \.id, content: { $char in
                TextField("pin digit", text:
                            Binding(get: {
                    char.char.description
                }, set: { newValue in
                    let newest: Character = newValue.last  ?? "0"
                    //This check is only needed if you only want numbers
                    if Int(newest.description) != nil{
                        char.char = newest
                    }
                    //Set the new focus
                    DispatchQueue.main.async {
                        setFocus()
                    }
                })
                ).textFieldStyle(.roundedBorder)
                    .focused($focusedField, equals: char)
            })
            
        }.onAppear(perform: {
            //Set the initial value of the text fields
            //By using unique characters you can keep the order
            pinDict = pin.description.uniqueCharacters()
            
        })
    }
    func setFocus(){
        //Default to the first box when focus is not set or the user reaches the last box
        if focusedField == nil || focusedField == pinDict.last{
            focusedField = pinDict.first
        }else{
            //find the index of the current character
            let idx = pinDict.firstIndex(of: focusedField!)
            //Another safety check for the index
            if idx == nil || pinDict.last == pinDict[idx!]{
                focusedField = pinDict.first
            }else{
                focusedField = pinDict[idx! + 1]
            }
        }
        //Update the Binding that came from the parent
        setPinBinding()
    }
    ///Updates the binding from the parent
    func setPinBinding(){
        var newPinInt = 0
        for n in pinDict{
            if n == pinDict.first{
                newPinInt = Int(n.char.description) ?? 0
            }else{
                newPinInt = Int(String(newPinInt) + n.char.description) ?? 0
            }
        }
        pin = newPinInt
    }
}


//Convert String to Unique characers
extension String{
    func uniqueCharacters() -> [UniqueCharacter]{
        let array: [Character] = Array(self)
        return array.uniqueCharacters()
    }
    func numberOnly() -> String {
        self.trimmingCharacters(in: CharacterSet(charactersIn: "-0123456789.").inverted)
    }
    
}
extension Array where Element == Character {
    
    func uniqueCharacters() -> [UniqueCharacter]{
        var array: [UniqueCharacter] = []
        
        for char in self{
            array.append(UniqueCharacter(char: char))
        }
        return array
    }
    
}

//String/Characters can be repeating so yu have to make them a unique value
struct UniqueCharacter: Identifiable, Equatable, Hashable{
    var char: Character
    var id: UUID = UUID()
}

@available(iOS 15.0, *)
struct PinView_Previews: PreviewProvider {
    static var previews: some View {
        PinParentView()
    }
}
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

1364 次

最近记录:

6 年,5 月 前