Home > Mobile >  How do I programmatically set secure text field and normal text field in swiftUI
How do I programmatically set secure text field and normal text field in swiftUI

Time:02-22

SwiftUI has two different forms of text fields, one is SecureField which hides input and TextField which doesn't hide input. Instead of creating two separate views, is there a way to create a single view that takes in a parameter to create both types while repeating as little code as possible?

CodePudding user response:

You just make a View with all the code you want for the SecureTextField and the TextField then all you have to do is call the HybridTextField where ever you need it.

import SwiftUI
struct HybridTextFieldUsageView: View {
    @State var password: String = "password"
    @State var viewSecure: Bool = true
    var body: some View {
        //Use this anywhere in your code
        HybridTextField(text: $password, titleKey: "password")
    }
}
///Contains all the code for the Secure and regular TextFields
struct HybridTextField: View {
    @Binding var text: String
    @State var isSecure: Bool = true
    var titleKey: String
    var body: some View {
        HStack{
            Group{
                if isSecure{
                    SecureField(titleKey, text: $text)
                    
                }else{
                    TextField(titleKey, text: $text)
                }
            }.textFieldStyle(.roundedBorder)
                .animation(.easeInOut(duration: 0.2), value: isSecure)
            //Add any common modifiers here so they dont have to be repeated for each Field
            Button(action: {
                isSecure.toggle()
            }, label: {
                Image(systemName: !isSecure ? "eye.slash" : "eye" )
            })
        }//Add any modifiers shared by the Button and the Fields here
    }
}

struct HybridTextField_Previews: PreviewProvider {
    static var previews: some View {
        HybridTextFieldUsageView()
    }
}

CodePudding user response:

In your view's body you can use a ternary to create the right textfield as needed without using a giant if/else block:

(self.isSecure ? AnyView(SecureField(placeholder, text: $value)) : AnyView(TextField(placeholder, text: $value)))

This will return a view that you can use operators on, which is useful if you're creating a custom text input. For example, the following would be painful if we had to do it twice for each kind of text field. Using a ternary in the actual view body keeps you from having two giant if/else blocks.

    VStack {
        ZStack(alignment: .leading) {
            Text(placeholder)
                .foregroundColor(Color(.placeholderText))
                .offset(y: $value.wrappedValue.isEmpty ? 0 : -25)
                .scaleEffect($value.wrappedValue.isEmpty ? 1 : 0.8, anchor: .leading)
            (self.isSecure ? AnyView(SecureField(placeholder, text: $value)) : AnyView(TextField(placeholder, text: $value)))
                .onChange(of: self.value) { newValue in
                    if self.onChange(newValue) != true {
                        self.value = previousValue
                    }
                    DispatchQueue.main.async {
                        self.previousValue = newValue
                    }
                }
        }
        .padding(.top, 15)
        .animation(.easeInOut(duration: 0.2))
        Divider()
         .frame(height: 1)
         .padding(.horizontal, 30)
         .background(Color.black)
    }
  • Related