I want to change the placeholder color of the TextField, but I can\'t find a method for it.
I tried to set foregroundColor
and accentColor
,
It's a bit modification for the @jfk's answer, we can create an extension for view
to simplify the modifier code inside the main view and also it can be used for Text
and Image
.
struct PlaceHolder<T: View>: ViewModifier {
var placeHolder: T
var show: Bool
func body(content: Content) -> some View {
ZStack(alignment: .leading) {
if show { placeHolder }
content
}
}
}
extension View {
func placeHolder<T:View>(_ holder: T, show: Bool) -> some View {
self.modifier(PlaceHolder(placeHolder:holder, show: show))
}
}
Usage in TextField:
Add this line of code .placeHolder(Text("Your placeholder"), show: text.isEmpty)
as a viewModifier
to TextField
.
TextField("", text: $text, onEditingChanged: { (changing) in
print("Changing: \(changing)")
}, onCommit: {
print("Committed!")
})
.placeHolder(Text("Your placeholder"), show: text.isEmpty)
Usage in Image:
Further more, as @EmilioPelaez suggested, I modified the code to support placeholder for any view for ex. Image
like below.
Image("your_image")
.placeHolder(Image("placeholder_image"), show: true)
There is no api for it (yet). BUT YOU CAN:
Use ZStack
and implement a placeholder yourself:
var body: some View {
ZStack(alignment: .leading) {
if text.isEmpty { Text("Placeholder").foregroundColor(.red) }
TextField("", text: $text)
}
}
Now you can use any kind of edit in it like a boss.
You can always create your own custom View
s to use everywhere:
struct CustomTextField: View {
var placeholder: Text
@Binding var text: String
var editingChanged: (Bool)->() = { _ in }
var commit: ()->() = { }
var body: some View {
ZStack(alignment: .leading) {
if text.isEmpty { placeholder }
TextField("", text: $text, onEditingChanged: editingChanged, onCommit: commit)
}
}
}
usage (TextField
with placeholder):
struct ContentView: View {
@State var text = ""
var body: some View {
CustomTextField(
placeholder: Text("placeholder").foregroundColor(.red),
text: $text
)
}
}
Eventually a ViewModifier that embeds the content in a ZStack is more elegant and less code:
public struct PlaceholderStyle: ViewModifier {
var showPlaceHolder: Bool
var placeholder: String
public func body(content: Content) -> some View {
ZStack(alignment: .leading) {
if showPlaceHolder {
Text(placeholder)
.padding(.horizontal, 15)
}
content
.foregroundColor(Color.white)
.padding(5.0)
}
}
}
Usage:
TextField("", text: $data)
.modifier(PlaceholderStyle(showPlaceHolder: data.isEmpty,
placeholder: "My Placeholder"))
If you want to preserve the original TextField and you don't mind adding Introspect to your project (https://github.com/siteline/SwiftUI-Introspect), you can do it by accessing the UIKit attributedPlaceholder
:
TextField("Email", text: $email)
.introspectTextField { uiTextField in
uiTextField.attributedPlaceholder = NSAttributedString(string: "placeholder text",
attributes: [NSAttributedString.Key.foregroundColor: UIColor.red])
}