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)
}
}
}
}
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)
}
}
}
CodePudding user response:
Here is my version of the 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. 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)
}
}