简体   繁体   English

使用 SwiftUI 的 TextField 描边边框文本

[英]TextField stroke border text with SwiftUI

Here is what I've done, but the problem is with Text background.这是我所做的,但问题在于文本背景。 It can be implemented on white background by setting the Text's background to white as well, but in case of image background it stays "strikedthrough".它也可以通过将文本的背景设置为白色来在白色背景上实现,但在图像背景的情况下,它会保持“删除线”。 You can find a source code below where I tried to make it as close to the result as possible.你可以在下面找到一个源代码,我试图让它尽可能接近结果。 How it could be resolved?怎么可能解决?

输入

struct CustomTextField: View {
    let placeholder: String
    @Binding var text: String

    var body: some View {
        TextField("", text: $text)
            .placeholder(when: $text.wrappedValue.isEmpty,
                         alignment: .leading,
                         placeholder: {
                Text(placeholder)
                    .foregroundColor(.gray)
                    .font(.system(size: 20))
                    .padding(.leading, 15)
            })
            .foregroundColor(.gray)
            .font(.system(size: 20))
            .padding(EdgeInsets(top: 15, leading: 10, bottom: 15, trailing: 10))
            .background {
                ZStack {
                    RoundedRectangle(cornerRadius: 5)
                        .stroke(.gray, lineWidth: 1)
                    Text(placeholder)
                        .foregroundColor(.gray)
                        .padding(2)
                        .font(.caption)
                        .frame(maxWidth: .infinity,
                               maxHeight: .infinity,
                               alignment: .topLeading)
                        .offset(x: 20, y: -10)
                }
            }
    }
}

Here is a solution using .trim on two RoundedRectangles based on the length of the label text, which should give you the result you want:这是一个基于标签文本长度在两个 RoundedRectangles 上使用 .trim 的解决方案,它应该会给你想要的结果:

struct CustomTextField: View {
    let placeholder: String
    @Binding var text: String

    @State private var width = CGFloat.zero
    @State private var labelWidth = CGFloat.zero

    var body: some View {
        TextField(placeholder, text: $text)
            .foregroundColor(.gray)
            .font(.system(size: 20))
            .padding(EdgeInsets(top: 15, leading: 10, bottom: 15, trailing: 10))
            .background {
                ZStack {
                    RoundedRectangle(cornerRadius: 5)
                        .trim(from: 0, to: 0.55)
                        .stroke(.gray, lineWidth: 1)
                    RoundedRectangle(cornerRadius: 5)
                        .trim(from: 0.565 + (0.44 * (labelWidth / width)), to: 1)
                        .stroke(.gray, lineWidth: 1)
                    Text(placeholder)
                        .foregroundColor(.gray)
                        .overlay( GeometryReader { geo in Color.clear.onAppear { labelWidth = geo.size.width }})
                        .padding(2)
                        .font(.caption)
                        .frame(maxWidth: .infinity,
                               maxHeight: .infinity,
                               alignment: .topLeading)
                        .offset(x: 20, y: -10)

                }
            }
            .overlay( GeometryReader { geo in Color.clear.onAppear { width = geo.size.width }})
            .onChange(of: width) { _ in
                print("Width: ", width)
            }
            .onChange(of: labelWidth) { _ in
                print("labelWidth: ", labelWidth)
            }

        
   }
}

在此处输入图像描述

Here is my version of the TextField.这是我的 TextField 版本。

在此处输入图像描述

在此处输入图像描述

struct TextInputField: View {
    let placeHolder: String
    @Binding var textValue: String
    
    var body: some View {
        ZStack(alignment: .leading) {
            Text(placeHolder)
                .foregroundColor(Color(.placeholderText))
                .offset(y: textValue.isEmpty ? 0 : -25)
                .scaleEffect(textValue.isEmpty ? 1: 0.8, anchor: .leading)
            TextField("", text: $textValue)
        }
        .padding(.top, textValue.isEmpty ? 0 : 15)
        .frame(height: 52)
        .padding(.horizontal, 16)
        .overlay(RoundedRectangle(cornerRadius: 12).stroke(lineWidth: 1).foregroundColor(.gray))
        .animation(.default)
    }
}

The above code is to create a CustomTextField named TextInputField.上面的代码是创建一个名为TextInputField 的CustomTextField。 If you want to use the about component如果你想使用 about 组件

struct ContentView: View {
    
    @State var itemName: String = ""
    
    var body: some View {
         TextInputField(placeHolder: "Item Name": textValue: $itemName)
    }
}

I'm using @ChrisR's answer as a base for my answer, so instead of doing all that calculation with two RoundedRectangles and label's width;我使用@ChrisR 的答案作为我的答案的基础,所以不是用两个 RoundedRectangles 和标签的宽度进行所有计算; you can position the Text on top and give it a background matching the app's background color您可以将 Text 放在顶部并为其提供与应用程序的背景颜色相匹配的背景

    struct FloatingTitleTextField: View {
    
    let placeholder: String
    @Binding var text: String
    
    var body: some View {
        TextField("Placeholder", text: $text)
            .foregroundColor(.gray)
            .font(.system(size: 20))
            .padding(EdgeInsets(top: 15, leading: 10, bottom: 15, trailing: 10))
            .background {
                ZStack {
                    RoundedRectangle(cornerRadius: 5)
                        .stroke(.black, lineWidth: 1)
                    Text(placeholder)
                        .foregroundColor(.gray)
                        .padding(2)
                        .background()
                        .frame(maxWidth: .infinity,
                               maxHeight: .infinity,
                               alignment: .topLeading)
                    
                        .offset(x: 20, y: -10)
                }
            }
    }
}

When calling the textfield you do it like this调用文本字段时,您会这样做

FloatingTitleTextField(placeholder: "Placeholder", text: $text)

I also found this article very helpful我也发现这篇文章很有帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM