UISearchBar change placeholder color
Asked Answered
L

18

53

Has anyone any idea or code sample on how can I change the text color of the placeholder text of a UISearchBar?

Lannie answered 6/8, 2012 at 11:44 Comment(4)
I think this post will help you #1340724Hepburn
I have already looked at it. This post concerns a UITextfield. Subclassing a UITextfield and overriding the -drawPlaceholderInRect method would certainly help. However, UISearchBar is not a subclass of UITextfield, and as such, I can't override this method.Lannie
sorry, I don't know this. UISearchBar is subclass of UIView, and I think you can subclass from it and try override drawRect method, adding in it code from previous post. Maybe this helpHepburn
For Swift 3. I found a solution here: Customize textfield easilyEspinosa
E
83

for iOS5+ use the appearance proxy

[[UILabel appearanceWhenContainedIn:[UISearchBar class], nil] setTextColor:[UIColor redColor]];
Epitaph answered 2/7, 2013 at 10:2 Comment(5)
Since my post I had found the answer, and indeed this is the best way to do it. Clean, simple and it doesn't break anything.Lannie
This is not really valid. UILabel doesn't support customization this way, because the textColor property of UILabel is not marked with UI_APPEARANCE_SELECTOR as required by the documentation. See also #11839544Quita
This is working for me only if I add some placeholder in Stroyboard.. Directly setting placeholder through code doesnt work if we dont have some placeholder in the storyboard.. wiredArmillary
I gave this thing an up-vote by accident. It does not work well. People should use: #1340724Kaph
this is not a valid answer, see my answer belowAudwin
K
31

Found the answer from Change UITextField's placeholder text color programmatically

// Get the instance of the UITextField of the search bar
UITextField *searchField = [searchBar valueForKey:@"_searchField"];

// Change search bar text color
searchField.textColor = [UIColor redColor];

// Change the search bar placeholder text color
[searchField setValue:[UIColor blueColor] forKeyPath:@"_placeholderLabel.textColor"];
Kalie answered 13/9, 2012 at 16:55 Comment(5)
Anyone tried to submit an app with that code? Shouldn't be much of a problem... but who can say that for sure...Morphology
Although this code works, I would trust any app submission with that, as it violates Apple's regulations.Lannie
My app is ok to submit to appstore with this solution. :)Gromme
I'd be worried this could suddenly start crashing with an iOS update.Gorlin
What about the prompt parameter??Foggia
N
22

First solution is OK, but if you use multiple UISearchBar, or create a lot of instances it may fail. The one solution that always work for me is to use also appearance proxy but directly on UITextField

   NSDictionary *placeholderAttributes = @{
                                            NSForegroundColorAttributeName: [UIColor darkButtonColor],
                                            NSFontAttributeName: [UIFont fontWithName:@"HelveticaNeue" size:15],
                                            };

    NSAttributedString *attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.searchBar.placeholder
                                                                                attributes:placeholderAttributes];

    [[UITextField appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setAttributedPlaceholder:attributedPlaceholder];
Notification answered 3/4, 2015 at 11:16 Comment(2)
It's the only solution that worked correctly for me, other solutions failed when navigating the viewController hierarchy back and forth, and destroying / recreating the search barSoapbox
This should be the accepted solution for ObjC/iOS 13Pandarus
S
19

Here is a Solution for Swift:

Swift 2

var textFieldInsideSearchBar = searchBar.valueForKey("searchField") as? UITextField
textFieldInsideSearchBar?.textColor = UIColor.whiteColor()

var textFieldInsideSearchBarLabel = textFieldInsideSearchBar!.valueForKey("placeholderLabel") as? UILabel
textFieldInsideSearchBarLabel?.textColor = UIColor.whiteColor()

Swift 3

let textFieldInsideSearchBar = searchBar.value(forKey: "searchField") as? UITextField
textFieldInsideSearchBar?.textColor = UIColor.white

let textFieldInsideSearchBarLabel = textFieldInsideSearchBar!.value(forKey: "placeholderLabel") as? UILabel
textFieldInsideSearchBarLabel?.textColor = UIColor.white
Seng answered 25/6, 2015 at 12:28 Comment(5)
Ill think so. Its the same solution other users recommend.Seng
How about the prompt?! (not the placeholder)Foggia
Try to set the tintcolor for the textFieldInsideSearchBar - should work fine!Seng
Works on iOS 10.2.1Barney
Works great but can you link to the apple docs in this topic. Im having trouble finding it. Thanks in advance.Sulphathiazole
S
14

It is easy from iOS 13.0 onwards, You can simply use searchTextField property of a search bar to update attributed properties of the placeholder.

self.searchController.searchBar.searchTextField.attributedPlaceholder =  NSAttributedString.init(string: "Search anything...", attributes: [NSAttributedString.Key.foregroundColor:UIColor.red])

One line solution

Slice answered 2/11, 2020 at 9:33 Comment(0)
F
11

Try this and see: (I tested below code with Swift 4.1 - Xcode 9.3-beta4)

@IBOutlet weak var sbSearchBar: UISearchBar!

if let textfield = sbSearchBar.value(forKey: "searchField") as? UITextField {

    textfield.backgroundColor = UIColor.yellow
    textfield.attributedPlaceholder = NSAttributedString(string: textfield.placeholder ?? "", attributes: [NSAttributedStringKey.foregroundColor : UIColor.red])

    textfield.textColor = UIColor.green

    if let leftView = textfield.leftView as? UIImageView {
        leftView.image = leftView.image?.withRenderingMode(.alwaysTemplate)
        leftView.tintColor = UIColor.red
    }
}

Here is result:

enter image description here

Fahland answered 15/3, 2018 at 14:16 Comment(1)
That's awesome, but if that isn't documented how reliable do you think it is as an interface? I will use it if it doesn't get the app rejected and it's unlikely Apple will suddenly change it. (Don't see why they would)Cariotta
C
7
if let textFieldInsideSearchBar = searchBar.value(forKey: "searchField") as ? UITextField {
    textFieldInsideSearchBar ? .textColor = UIColor.white

    if let textFieldInsideSearchBarLabel = textFieldInsideSearchBar!.value(forKey: "placeholderLabel") as ? UILabel {
        textFieldInsideSearchBarLabel ? .textColor = UIColor.white

        if let clearButton = textFieldInsideSearchBar ? .value(forKey: "clearButton") as!UIButton {

            clearButton.setImage(clearButton.imageView ? .image ? .withRenderingMode(.alwaysTemplate),
                for : .normal)
            clearButton.tintColor = UIColor.white
        }
    }

    let glassIconView = textFieldInsideSearchBar ? .leftView as ? UIImageView

    glassIconView ? .image = glassIconView ? .image ? .withRenderingMode(.alwaysTemplate)
    glassIconView ? .tintColor = UIColor.white
}
Colan answered 20/11, 2016 at 16:15 Comment(0)
N
6

Swift 5 - ios 13:

Those who are stuck let me tell you it is going to work only in viewDidLayoutSubviews not in viewDidLoad

override func viewDidLayoutSubviews() {

    setupSearchBar(searchBar: YourSearchBar)

}

    func setupSearchBar(searchBar : UISearchBar) {

    searchBar.setPlaceholderTextColorTo(color: UIColor.white)        

   }

extension UISearchBar
{
    func setPlaceholderTextColorTo(color: UIColor)
    {
        let textFieldInsideSearchBar = self.value(forKey: "searchField") as? UITextField
        textFieldInsideSearchBar?.textColor = color
        let textFieldInsideSearchBarLabel = textFieldInsideSearchBar!.value(forKey: "placeholderLabel") as? UILabel
        textFieldInsideSearchBarLabel?.textColor = color
    }
}

Happy coding :)

Nierman answered 27/2, 2020 at 10:1 Comment(0)
A
5

worked for me on IOS 13

searchBar.searchTextField.attributedPlaceholder = NSAttributedString(
    string: "Search something blabla",
    attributes: [.foregroundColor: UIColor.red]
)
Ancelin answered 14/2, 2021 at 18:45 Comment(1)
Best answer hereMoise
P
4

It looks like Apple does not want us to play with the placeholder colors when it comes to UISearchBar class. So, let's create our own placeholder label!

  • No subclassing.
  • Works with iOS 13 SDK.
  • Just one innocent workaround.

enter image description here

let searchBar = searchController.searchBar
// ...
// Configure `searchBar` if needed
// ...

let searchTextField: UITextField
if #available(iOS 13, *) {
    searchTextField = searchBar.searchTextField
} else {
    searchTextField = (searchBar.value(forKey: "searchField") as? UITextField) ?? UITextField()
}

// Since iOS 13 SDK, there is no accessor to get the placeholder label.
// This is the only workaround that might cause issued during the review.
if let systemPlaceholderLabel = searchTextField.value(forKey: "placeholderLabel") as? UILabel {
    // Empty or `nil` strings cause placeholder label to be hidden by the search bar
    searchBar.placeholder = " "

    // Create our own placeholder label
    let placeholderLabel = UILabel(frame: .zero)

    placeholderLabel.text = "Search"
    placeholderLabel.font = UIFont.systemFont(ofSize: 17.0, weight: .regular)
    placeholderLabel.textColor = UIColor.blue.withAlphaComponent(0.5)

    systemPlaceholderLabel.addSubview(placeholderLabel)

    // Layout label to be a "new" placeholder
    placeholderLabel.leadingAnchor.constraint(equalTo: systemPlaceholderLabel.leadingAnchor).isActive = true
    placeholderLabel.topAnchor.constraint(equalTo: systemPlaceholderLabel.topAnchor).isActive = true
    placeholderLabel.bottomAnchor.constraint(equalTo: systemPlaceholderLabel.bottomAnchor).isActive = true
    placeholderLabel.translatesAutoresizingMaskIntoConstraints = false
    placeholderLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
} else {
    searchBar.placeholder = ""
}
Privilege answered 15/11, 2019 at 6:16 Comment(0)
D
3

Swift 3

UILabel.appearance(whenContainedInInstancesOf: [UISearchBar.self]).textColor = UIColor.white
Dispassionate answered 1/2, 2017 at 18:27 Comment(0)
E
3

iOS 13

Previous solutions may not work on iOS 13 because new searchTextField has been added, and you can set attributed string on it.

I wrapped that into category:

@interface UISearchBar (AttributtedSetter)
- (void)setThemedPlaceholder:(NSString*)localizationKey;
@end

@implementation UISearchBar (AttributtedSetter)

- (void)setThemedPlaceholder:(NSString*)localizationKey {
    ThemeObject *currentTheme = [[ThemeManager standardThemeManager] currentTheme];
    self.searchTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:NSLocalizedString(localizationKey, @"") attributes:@{NSForegroundColorAttributeName : currentTheme.colorSearchBarText}];
}

@end
Evie answered 23/10, 2019 at 8:7 Comment(1)
I've tried assigning to attributedPlaceholder multiple times with no luck. It accepts the string contents, but does not change the text color. The search bar is inside a navigation item.Tabulate
T
3

iOS 13

Use a custom search bar subclass.

This also works when part of a UISearchController inside a UINavigationItem (with hidesSearchBarWhenScrolling = true).

We want to apply our changes immediately after UIAppearance proxies are being applied since those are the most likely root cause:

class MySearchBar : UISearchBar {
    // Appearance proxies are applied when a view is added to a view hierarchy, so apply your tweaks after that:
    override func didMoveToSuperview() {
        super.didMoveToSuperview() // important! - system colors will not apply correctly on ios 11-12 without this

        let placeholderColor = UIColor.white.withAlphaComponent(0.75)
        let placeholderAttributes = [NSAttributedString.Key.foregroundColor : placeholderColor]
        let attributedPlaceholder = NSAttributedString(string: "My custom placeholder", attributes: placeholderAttributes)
        self.searchTextField.attributedPlaceholder = attributedPlaceholder
        
        // Make the magnifying glass the same color
        (self.searchTextField.leftView as? UIImageView)?.tintColor = placeholderColor
    }
}

// Override `searchBar` as per the documentation
private class MySearchController : UISearchController {
    private lazy var customSearchBar = MySearchBar()
    override var searchBar: UISearchBar { customSearchBar }
}

That took quite some time to get working properly...

Tabulate answered 1/3, 2020 at 0:19 Comment(0)
V
2

Try this:

[self.searchBar setValue:[UIColor whatever] forKeyPath:@"_searchField._placeholderLabel.textColor"];

You can also set this in storyboard, select search bar, add entry under User Defined Runtime Attributes:

_searchField._placeholderLabel.textColor

of type Color and select the color you need.

Vestpocket answered 26/1, 2015 at 14:29 Comment(0)
L
0

After surveyed a couple of answers, I come out this, hope its help

for (UIView *subview in searchBar.subviews) {
    for (UIView *sv in subview.subviews) {
        if ([NSStringFromClass([sv class]) isEqualToString:@"UISearchBarTextField"]) {

            if ([sv respondsToSelector:@selector(setAttributedPlaceholder:)]) {
                ((UITextField *)sv).attributedPlaceholder = [[NSAttributedString alloc] initWithString:searchBar.placeholder attributes:@{NSForegroundColorAttributeName: [UIColor whiteColor]}];
            }
            break;
        }
    }
}
Lecherous answered 19/5, 2015 at 5:38 Comment(1)
I subclassed the UISearchBar class, and then I used an attributed placeholder like you did. But in my subclass, I added override var placeholder: String? { didSet { changePlaceholderColor(str: placeholder ?? "") } }, that way, whenever I change the placeholder text on this searchBar, it will automatically make the placeholder text the correct color. If I didn't do this, then it would override my placeholder color if I ever set a normal placeholder.Potty
C
0

This solution works on Xcode 8.2.1. with Swift 3.0. :

extension UISearchBar
{
    func setPlaceholderTextColorTo(color: UIColor)
    {
        let textFieldInsideSearchBar = self.value(forKey: "searchField") as? UITextField
        textFieldInsideSearchBar?.textColor = color
        let textFieldInsideSearchBarLabel = textFieldInsideSearchBar!.value(forKey: "placeholderLabel") as? UILabel
        textFieldInsideSearchBarLabel?.textColor = color
    }
}

Usage example:

searchController.searchBar.setPlaceholderTextColorTo(color: mainColor)
Counterstamp answered 24/2, 2017 at 10:43 Comment(0)
B
-1

This is an old question, but for anyone stumbling on it nowadays, you can change the search icon on iOS 8.x - 10.3 using the following:

[_searchBar setImage:[UIImage imageNamed:@"your-image-name"] forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];

Regarding the placeholder text color, you may check my other answer, which uses a Category, here: UISearchBar change placeholder color

Bogbean answered 2/6, 2017 at 12:51 Comment(0)
B
-3

Try this:

  UITextField *searchField = [searchbar valueForKey:@"_searchField"];
  field.textColor = [UIColor redColor]; //You can put any color here.
Bonne answered 6/8, 2012 at 13:24 Comment(3)
I don't want to change the color of the normal text. I want to change the color of the placeholder text.Lannie
This is NOT OK! You are accessing a PRIVATE iVAR when you do this and this might get your app rejected from app store.Goings
@AlexanderW : If this was meant not to be used, you won't be able to access it... Everyone around the world use this thing for changing color of textfield placeholder color change.... my app has never been rejected due to this... but its just a solution, may not a perfect one.....Bonne

© 2022 - 2024 — McMap. All rights reserved.