使用 SwiftUI 的 TextField 描边边框文本

TextField stroke border text with SwiftUI

这是我所做的,但问题出在文本背景上。它也可以通过将文本的背景设置为白色在白色背景上实现,但在图像背景的情况下它保持“删除线”。你可以在下面找到源代码,我试图让它尽可能接近结果。如何解决?

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)
                }
            }
    }
}

这是我的 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)
    }
}

以上代码是创建一个名为TextInputField的CustomTextField。如果你想使用关于组件

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

这是一个基于标签文本的长度在两个 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)
            }

        
   }
}