在 SwiftUI 中向 TextField/SecureField 添加图像,向占位符文本添加填充

Posted

技术标签:

【中文标题】在 SwiftUI 中向 TextField/SecureField 添加图像,向占位符文本添加填充【英文标题】:Add Image to TextField/SecureField in SwiftUI, add padding to placeholder text 【发布时间】:2020-03-22 07:38:27 【问题描述】:

我在 SwiftUI 中创建了一个文本字段和一个安全文本字段,但我不知道如何在 SwiftUI 中将图像添加到我的文本字段/安全文本字段中。与旧版本的 Swift 相比,SwiftUI 的在线文档并不多。我还想将(占位符/键入的文本)移动指定的量,例如向右移动 30 点。我也在尝试查看背景颜色是否会从白色变为红色,但正如您所见,它在我的代码中,对 UI 没有影响。

注意:我的代码中有前面调用的 GeometryReader 以及用户名和密码的 @state 变量。

我的目标是让它看起来像这样,现在它看起来像这样

            VStack (spacing: deviceSize.size.height * (50/812)) 
                TextField ("Username", text: self.$username)
                    .foregroundColor(.black)//text color when you type
                    .accentColor(.blue)//cursor color
                    .background(Color(.red))//????
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                    .cornerRadius(50)

                // .border(Color.white)
                //.font(.title)

                SecureField ("Password", text: self.$password)
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                    .cornerRadius(50)

            
            .padding(.init(top: 0, leading: deviceSize.size.width * (38/375), bottom: 0, trailing: deviceSize.size.width * (38/375)))

【问题讨论】:

【参考方案1】:

实现这种设计的最简单方法是将ImageTextField 放在HStack 中,并给它一个圆形背景。密码字段稍微复杂一些,因为它需要一个额外的Button,并且当您隐藏/显示密码时,您需要在TextFieldSecureField 之间进行更改。这是我的看法:

struct ContentView: View 
    
    @State private var username = ""
    @State private var password = ""
    @State private var showPassword = false
    
    var body: some View 
        ZStack 
            Color.blue
            VStack 
                HStack 
                    Image(systemName: "person")
                        .foregroundColor(.secondary)
                    TextField("Username",
                              text: $username)
                   .padding()
                    .background(Capsule().fill(Color.white))
                HStack 
                    Image(systemName: "lock")
                        .foregroundColor(.secondary)
                    if showPassword 
                        TextField("Password",
                        text: $password)
                     else 
                    SecureField("Password",
                              text: $password)
                    
                    Button(action:  self.showPassword.toggle()) 
                        
                        Image(systemName: "eye")
                        .foregroundColor(.secondary)
                    
                   .padding()
                    .background(Capsule().fill(Color.white))
               .padding()
        
    

【讨论】:

很好的答案。请注意,图像帧未正确对齐。给两个图像一个框架宽度,它们的宽度和高度。或者选择使用纵横比。让它更干净一点:-) 善于观察细节@TobiasHesselink! @LuLuGaGa 在使用 resizable () 方法之前,文本字段左侧的图像没有显示给我 @bain 你是复制粘贴了我的例子还是用了其他图片? @LuLuGaGa 我使用了自己的图像并调整了它们的大小,我看到你使用了系统默认图像,这似乎给你一个更大的图标,但由于某种原因它没有出现在我身上我刚刚解决了我的问题。现在一切都很好,尽管感谢您对此的帮助。你让我成功了 95%。【参考方案2】:

我真的是 SwiftUI 的新手,但我找到了一个解决方法,我希望它不会在未来造成任何问题,或者这将是一个重要的教训。如果有人有任何建议,我也会很感激! =]

我将 TextField 和图像嵌入到 ZStack 中,然后将图像放入 View 中并为视图提供填充。

struct FormInputBox: View 

@State private var text: String = ""
@State private var textFieldState: TextFieldState = .empty

private var textFieldType: TextFieldType
private var textViewPlaceholder = ""

init(placeholder: String,
     textFieldType: TextFieldType) 
    self.textViewPlaceholder = placeholder
    self.textFieldType = textFieldType


var body: some View 
    ZStack(alignment: Alignment(horizontal: .trailing, vertical: .center), content: 
        TextField(textViewPlaceholder, text: $text)
            .textFieldStyle(MyTextFieldStyle(textFieldState: $textFieldState))
        AnyView(
            Image("tick")
                .resizable()
                .frame(width: 20, height: 20, alignment: .leading)
        )
            .padding(32)
        
    )

【讨论】:

这是一个非常优雅的解决方案,不需要考虑隐藏/伪装文本字段输入的背景。但是,您不需要将图像包装在 AnyView 中。谢谢!【参考方案3】:

我创建了一个名为 ASTextField 的可重用 SwiftUI 文本字段,其工作方式类似于 UIKit 中的 textField,您可以在其中添加 leftViewrightView textField 并可以处理与它们相关的事件。

你可以在gist找到这个实现。

你可以这样消费它:-

struct ContentView : View , ASTextFieldDelegate 

   let leftImage = UIImage(systemName: "calendar")
   let rightImage = UIImage(systemName: "eye")
   let rightImage1 = UIImage(systemName: "trash")

   @State var text : String? = "with simple binding"
   @State var text1 : String? = "with closure for right item"
   @State var text2 : String? = "for secure entry"

   var body: some View 
       VStack 
          Spacer()
           ASTextField(text: $text)

          Spacer()

          ASTextField(rightItem: rightImage1, leftItem: leftImage, handleLeftTap: 
            print("right icon tapped.....")
          , delegate: self, text: $text1)

          Spacer()

          ASTextField(rightItem: rightImage, leftItem: leftImage, isSecuredEntry: true, delegate: self, text: $text2)

          Spacer()

      
   

【讨论】:

【参考方案4】:

“Introspect”会为你工作

文本域() .introspectTextField 中的文本字段 textfield.rightViewMode = .unlessEditing textfield.rightView = UIImageView(图像:UIImage(命名:ImageCatalog.error.content))

【讨论】:

以上是关于在 SwiftUI 中向 TextField/SecureField 添加图像,向占位符文本添加填充的主要内容,如果未能解决你的问题,请参考以下文章

在 swiftUI 2 中向 MapKit 添加 MapMarker

在 SwiftUI 中向 TextField/SecureField 添加图像,向占位符文本添加填充

如何在 MacOS 的 SwiftUI 中向 TextEditor 添加焦点环

SwiftUI:我可以向 TabView 添加更多视图,然后是选项卡项吗?

如何从 MKMapView didSelect 注释更新封装的 SwiftUI 视图

在 VUE 中向 href 添加数据