Reputation: 475
So I'd like my textfield to have a customizable placeholder text so I decided to put a Text() element in a ZStack in front of the text field. The only problem is, this Text() item blocks the selection of the textfield that is behind it (AKA when I click the placeholder I want the TextField to be clicked). Unfortunately, this Text() element blocks the click. I tried using the .allowsHitTesting() property as seen below but that also didn't work, and I'm not sure why.
struct ContentView: View {
@State var text: String = ""
var body: some View {
ZStack {
TextField("", text: self.$text)
.background(Color.red)
.foregroundColor(Color.white)
if text.isEmpty {
Text("Placeholder")
.allowsHitTesting(false)
}
}
}
}
Upvotes: 1
Views: 1333
Reputation: 257711
It can be done with custom text field style.
Here is a demo of solution (or parameters can be tuned). Tested with Xcode 12 / iOS 14 (border is just for visibility)
struct PlaceholderStyle: TextFieldStyle {
let isActive: Bool
var placeholder = "Placeholder"
var color = Color.white
var backgrond = Color.red
func _body(configuration: TextField<_Label>) -> some View {
Text("\(isActive ? placeholder : "")")
.foregroundColor(isActive ? color : .clear)
.background(isActive ? backgrond : .clear)
.frame(maxWidth: .infinity, alignment: .leading)
.overlay(configuration)
}
}
struct DemoView: View {
@State private var text = ""
var body: some View {
TextField("", text: $text)
.border(Color.gray).padding(.horizontal)
.textFieldStyle(PlaceholderStyle(isActive: text.isEmpty))
}
}
Upvotes: 2
Reputation: 17695
See if this fits your needs:
struct ContentView: View {
@State var text = ""
var body: some View {
ZStack(alignment: .leading) {
if text.isEmpty { Text("Placeholder")
.foregroundColor(.red)
.background(Color.yellow)
}
TextField("", text: $text)
.background(text.isEmpty ? Color.clear : Color.yellow)
}
}
}
Upvotes: 1