Search code examples
swiftswiftui

SwiftUI. How to change the placeholder color of the TextField?


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, but it doesn't change the placeholder color.

Here is the code:

TextField("Placeholder", $text)
    .foregroundColor(Color.red)
    .accentColor(Color.green)

Maybe there is no API for this yet?


Solution

  • From iOS 15

    You can use the prompt argument of the TextField:

    TextField("", text: $text, prompt: Text("Placeholder"))
    

    Below iOS 15

    Custom placeholder supporting all iOS versions with any appearance:

    Use a custom placeholder modifier to show any view as the holder of any other view! e.g:

    TextField("", text: $text)
        .placeholder(when: text.isEmpty) {
            Text("Placeholder recreated").foregroundColor(.gray)
    }
    

    Demo1

    💡 It's a simple ZStack that you can in a View extension like:

    extension View {
        func placeholder<Content: View>(
            when shouldShow: Bool,
            alignment: Alignment = .leading,
            @ViewBuilder placeholder: () -> Content) -> some View {
    
            ZStack(alignment: alignment) {
                placeholder().opacity(shouldShow ? 1 : 0)
                self
            }
        }
    }
    

    Note that the above method also works on any kind of View like TextField, TextEditor, Image, etc.


    🎁 Bonus: Full Customization!

    With the extension approach, you can apply any kind of style to the placeholder like this gradient placeholder with image:

    Demo2

    ✅ If you are interested, Here is how to apply resizable gradient on any view


    💡 The Art of the simplicity

    Most of the time you need to pass just a string and a gray placeholder like:

    TextField("", text: $text)
        .placeholder("Placeholder", when: text.isEmpty)
    

    you can write a simple wrapper around the above extension for it:

    extension View {
        func placeholder(
            _ text: String,
            when shouldShow: Bool,
            alignment: Alignment = .leading) -> some View {
                
            placeholder(when: shouldShow, alignment: alignment) { Text(text).foregroundColor(.gray) }
        }
    }
    

    Just like that 😉