Home > Software design >  TextField stroke border text with SwiftUI
TextField stroke border text with SwiftUI

Time:03-10

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?

Inputs

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

CodePudding user response:

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:

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

        
   }
}

enter image description here

CodePudding user response:

Here is my version of the TextField.

enter image description here

enter image description here

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. If you want to use the about component

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