专注于 SwiftUI 中的下一个 TextField/SecureField

Dan*_*yan 11 ios swiftui

我在 SwiftUI 中构建了一个登录屏幕。SecureField当用户完成输入他们的电子邮件时,我想专注于密码。我怎样才能做到这一点?

struct LoginView: View {
    @State var username: String = ""
    @State var password: String = ""

    var body: some View {
        ScrollView {
            VStack {
                TextField("Email", text: $username)
                    .padding()
                    .frame(width: 300)
                    .background(Color(UIColor.systemGray5))
                    .cornerRadius(5.0)
                    .padding(.bottom, 20)
                    .keyboardType(.emailAddress)

                SecureField("Password", text: $password)
                    .padding()
                    .frame(width: 300)
                    .background(Color(UIColor.systemGray5))
                    .cornerRadius(5.0)
                    .padding(.bottom, 20)

                Button(action: {

                }, label: {
                    Text("Login")
                        .padding()
                        .frame(width: 300)
                        .background((username.isEmpty || password.isEmpty) ? Color.gray : Color(UIColor.cricHQOrangeColor()))
                        .foregroundColor(.white)
                        .cornerRadius(5.0)
                        .padding(.bottom, 20)
                }).disabled(username.isEmpty || password.isEmpty)
Run Code Online (Sandbox Code Playgroud)

paw*_*222 14

iOS 15+

在 iOS 15 中,我们现在可以用来@FocusState控制应该关注哪个字段。

以下是如何在键盘上方添加按钮以聚焦上一个/下一个字段的示例:

在此输入图像描述

struct ContentView: View {
    @State private var email: String = ""
    @State private var username: String = ""
    @State private var password: String = ""

    @FocusState private var focusedField: Field?

    var body: some View {
        NavigationView {
            VStack {
                TextField("Email", text: $email)
                    .focused($focusedField, equals: .email)
                TextField("Username", text: $username)
                    .focused($focusedField, equals: .username)
                SecureField("Password", text: $password)
                    .focused($focusedField, equals: .password)
            }
            .toolbar {
                ToolbarItem(placement: .keyboard) {
                    Button(action: focusPreviousField) {
                        Image(systemName: "chevron.up")
                    }
                    .disabled(!canFocusPreviousField()) // remove this to loop through fields
                }
                ToolbarItem(placement: .keyboard) {
                    Button(action: focusNextField) {
                        Image(systemName: "chevron.down")
                    }
                    .disabled(!canFocusNextField()) // remove this to loop through fields
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
extension ContentView {
    private enum Field: Int, CaseIterable {
        case email, username, password
    }
    
    private func focusPreviousField() {
        focusedField = focusedField.map {
            Field(rawValue: $0.rawValue - 1) ?? .password
        }
    }

    private func focusNextField() {
        focusedField = focusedField.map {
            Field(rawValue: $0.rawValue + 1) ?? .email
        }
    }
    
    private func canFocusPreviousField() -> Bool {
        guard let currentFocusedField = focusedField else {
            return false
        }
        return currentFocusedField.rawValue > 0
    }

    private func canFocusNextField() -> Bool {
        guard let currentFocusedField = focusedField else {
            return false
        }
        return currentFocusedField.rawValue < Field.allCases.count - 1
    }
}
Run Code Online (Sandbox Code Playgroud)


Ash*_*nna 7

给你 - 本机 SwiftUI 解决方案。感谢 Gene Z. Ragan 在之前的回答中提供了 SwiftUI 文档的链接

struct TextFieldTest: View {
    @FocusState private var emailFocused: Bool
    @FocusState private var passwordFocused: Bool
    @State private var username: String = ""
    @State private var password: String = ""


    var body: some View {
        TextField("User name (email address)", text: $username)
            .focused($emailFocused)
            .onSubmit {
                passwordFocused = true
            }

        TextField("Enter Password", text: $password)
            .focused($passwordFocused)
    }

}
Run Code Online (Sandbox Code Playgroud)


Gen*_*gan 6

使用 UIKit 时,可以通过设置响应者链来实现这一点。这在 SwiftUI 中不可用,因此在有更复杂的焦点和响应系统之前,您可以利用TextFieldonEditingChanged更改

然后,您需要根据存储的状态变量管理每个字段的状态。它最终可能比您想做的工作更多。

幸运的是,您可以通过使用 UIViewRepresentable 回退到 SwiftUI 中的 UIKit。

下面是一些使用 UIKit 响应器系统管理文本字段焦点的代码:

import SwiftUI

struct KeyboardTypeView: View {
    @State var firstName = ""
    @State var lastName = ""
    @State var focused: [Bool] = [true, false]

    var body: some View {
        Form {
            Section(header: Text("Your Info")) {
                TextFieldTyped(keyboardType: .default, returnVal: .next, tag: 0, text: self.$firstName, isfocusAble: self.$focused)
                TextFieldTyped(keyboardType: .default, returnVal: .done, tag: 1, text: self.$lastName, isfocusAble: self.$focused)
                Text("Full Name :" + self.firstName + " " + self.lastName)
            }
        }
}
}



struct TextFieldTyped: UIViewRepresentable {
    let keyboardType: UIKeyboardType
    let returnVal: UIReturnKeyType
    let tag: Int
    @Binding var text: String
    @Binding var isfocusAble: [Bool]

    func makeUIView(context: Context) -> UITextField {
        let textField = UITextField(frame: .zero)
        textField.keyboardType = self.keyboardType
        textField.returnKeyType = self.returnVal
        textField.tag = self.tag
        textField.delegate = context.coordinator
        textField.autocorrectionType = .no

        return textField
    }

    func updateUIView(_ uiView: UITextField, context: Context) {
        if isfocusAble[tag] {
            uiView.becomeFirstResponder()
        } else {
            uiView.resignFirstResponder()
        }
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, UITextFieldDelegate {
        var parent: TextFieldTyped

        init(_ textField: TextFieldTyped) {
            self.parent = textField
        }

        func updatefocus(textfield: UITextField) {
            textfield.becomeFirstResponder()
        }

func textFieldShouldReturn(_ textField: UITextField) -> Bool {

            if parent.tag == 0 {
                parent.isfocusAble = [false, true]
                parent.text = textField.text ?? ""
            } else if parent.tag == 1 {
                parent.isfocusAble = [false, false]
                parent.text = textField.text ?? ""
         }
        return true
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

您可以参考此问题以获取有关此特定方法的更多信息。

希望这可以帮助!