Как создать пользовательский TextInput с возможностью действовать как в качестве безопасного поля (со значком глаза), так и обычного TextField в SwiftUI - PullRequest
1 голос
/ 27 апреля 2020

Я новичок в SwiftUI. Я хотел разработать собственный TextField, который принимает параметр для изменения себя в качестве безопасного поля с возможностью показать и скрыть пароль. Но я застрял с проблемой сейчас. Поскольку вызывающая сторона моего пользовательского текстового поля будет передавать переменную State в качестве параметра, я должен использовать здесь @Binding внутри моего класса. Но когда я использую привязку, текст исчезает при нажатии на значок глаза. Пожалуйста, исправьте меня, если в моих предположениях, описанных выше или закодированных ниже, есть какие-либо ошибки.

import SwiftUI

struct BTextInput: View {
    @Binding var valueHolder : String
    var hint : String?
    @State var isSecure: Bool?
    @State var isTextHidden: Bool = true

    var body: some View {
        HStack{
            if isSecure ?? false{

                if isTextHidden {
                    VStack{
                        SecureField("\(hint.optionalVal)" ,text : self.$valueHolder)
                            .lineLimit(1)
                            .multilineTextAlignment(.leading)
                            .padding(.horizontal,4)
                            .padding(.trailing,28)

                        Rectangle().frame(height: 0.5)
                            .foregroundColor(.gray)
                    }.overlay(
                        Button(action: {
                            self.isTextHidden.toggle()
                        }){
                            EyeImage(name: "eye")
                        }.padding(.top,2.5)
                        ,alignment: .topTrailing)
                }else{
                    VStack{
                        TextField("\(hint.optionalVal)" ,text : self.$valueHolder)
                            .lineLimit(1)
                            .multilineTextAlignment(.leading)
                            .padding(.horizontal,4)
                            .padding(.trailing,28)

                        Rectangle().frame(height: 0.5)
                            .foregroundColor(.gray)
                    }.overlay(
                        Button(action: {
                            self.isTextHidden.toggle()
                        }){
                            EyeImage(name: "eye.slash")
                        }.padding(.top,2.5)
                        ,alignment: .topTrailing)
                }
           }else{
                VStack{
                    TextField("\(hint.optionalVal)" ,text : self.$valueHolder)
                        .lineLimit(1)
                        .multilineTextAlignment(.leading)
                        .padding(.horizontal,4)

                    Rectangle().frame(height: 0.5)
                        .foregroundColor(.gray)
                }
            }
        }.padding()
    }
}
struct EyeImage: View {

    private var imageName: String
    init(name: String) {
        self.imageName = name
    }
    var body: some View {
        Image(systemName : imageName)
            .foregroundColor(.black)
    }
}

struct BTextInput_Previews: PreviewProvider {
    static var previews: some View {
        VStack{
            BTextInput(valueHolder: Binding.constant(""), hint: "Account")
            BTextInput(valueHolder: Binding.constant(""), hint: "Account", isSecure: true)
        }
    }
}

Этот код будет работать должным образом, если мы заменим '@Binding var valueHolder: String' на '@State var valueHolder: String ». Но мне нужно сохранить его как переменную привязки, так как это пользовательский TextInput.

Было бы замечательно, если бы вы могли предложить какой-либо лучший подход для достижения того же самого. (Также ошибки в моем коде / лучшие практики кодирования) Заранее спасибо

1 Ответ

0 голосов
/ 27 апреля 2020

Если не учитывать потерю фокуса при изменении видимости, все работает нормально. Я предполагаю, что вы запутались, используя постоянную привязку в Preview, потому что привязка, на самом деле, пассивна - она ​​отвечает за обновление состояния. Поэтому для предварительного просмотра компонента, зависящего от привязки, необходим вспомогательный вид с активным состоянием, как показано ниже:

struct BTextInput_Previews: PreviewProvider {
    struct TestSecureFieldSwitch: View {
        @State private var text = ""
        @State private var pass = ""
        var body: some View {
            VStack{
                BTextInput(valueHolder: $text, hint: "Account")
                BTextInput(valueHolder: $pass, hint: "Password", isSecure: true)
            }
        }
    }

    static var previews: some View {
        TestSecureFieldSwitch()
    }
}

Протестировано с Xcode 11.4 / iOS 13.4

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...