Cannot change search bar background color
Asked Answered
R

23

32

I have a search bar:

let searchBar:UISearchBar = UISearchBar(frame: CGRectMake((searchView.frame.width - UIScreen.mainScreen().bounds.width / 1.6) / 2, 0, UIScreen.mainScreen().bounds.width / 1.6, 24))

and I want to change text input part background color. For this I've tried:

searchBar.barTintColor = UIColor(red: 0/255, green: 74/255, blue: 103/255, alpha: 1)

searchBar.backgroundColor = UIColor.redColor()

but these both variants do not work. How can I change background color of my UISearchBar textInput part and what I did wrong?

Respiratory answered 17/11, 2015 at 7:24 Comment(2)
See demo project, I am add SearchBar in StoryBoard.Buttaro
I wanted to change the color around the rounded textField and tried all of the solutions below :D but it's just the barTintColor property that you tried above. Make sure to set isTranslucent to false in code or storyboard.Runoff
M
22

Like @aliamcami, all the answers before did not work as I would expect, either the answer did not work for me or it works but it needs too much "dummy" code. So I share another answer wrote in Swift 4 with simplified logic:

for textField in searchController.searchBar.subviews.first!.subviews where textField is UITextField {
    textField.subviews.first?.backgroundColor = .white
    textField.subviews.first?.layer.cornerRadius = 10.5 //I set 10.5 because is approximately the system value
    textField.subviews.first?.layer.masksToBounds = true
    //Continue changing more properties...
}

textField.subviews.first is the "_UISearchBarSearchFieldBackgroundView" subview which add visual effects behind the UIFieldEditor.


Edited

After some development and many bugs, I finished with this elegant solution (that I am sure Apple would not be happy to approve, but I do not know) that works from iOS 10 to iOS 12:

if let textField = searchBar.value(forKey: "searchField") as? UITextField {
    textField.backgroundColor = myColor
    //textField.font = myFont
    //textField.textColor = myTextColor
    //textField.tintColor = myTintColor
    // And so on...
    
    let backgroundView = textField.subviews.first
    if #available(iOS 11.0, *) { // If `searchController` is in `navigationItem`
        backgroundView?.backgroundColor = UIColor.white.withAlphaComponent(0.3) //Or any transparent color that matches with the `navigationBar color`
        backgroundView?.subviews.forEach({ $0.removeFromSuperview() }) // Fixes an UI bug when searchBar appears or hides when scrolling
    }
    backgroundView?.layer.cornerRadius = 10.5
    backgroundView?.layer.masksToBounds = true
    //Continue changing more properties...
}

When the searchBar is in the tableHeaderView the above code can be called in viewWillAppear, but if it is in the navigationItem on iOS 11 and above it should be called in viewDidAppear.

Martens answered 30/8, 2018 at 16:16 Comment(3)
the solution provided by @Ángel Téllez worked for me as well! Thanks Angel! Not sure if it will work for IOS 10 also but it works for 11. Also, had one minor UI glitch where for a flash ( under a second ), there is a white line that appears between the navigation header and the search bar controller. Don't know quite why this happens but glad that this works !Smut
Your are welcome, @sudhama. I am glad it works for at least someone :D. I updated my answer after some fixes I done after 3 months. The code works fine for me in iOS 10 and above from iPhone 5 to the XS. About the glitch, maybe could be that your must change the properties of the searchBar in viewWillAppear? Or maybe you are playing around with the shadowImage porperty of the searchBar and that cause the line under it reloads? I hope you can solve it :)Paluas
In order to avoid the search bar briefly flashing the old color when the search bar is in the navigationItem, instead of viewDidAppear I found I could put it in viewDidLayoutSubviews, after the call to super.Wenda
S
16

If you only want to change it in your ViewController and don't want anywhere else to effect then use

for view in searchBar.subviews {
            for subview in view.subviews {
                if subview .isKindOfClass(UITextField) {
                    let textField: UITextField = subview as! UITextField
                    textField.backgroundColor = UIColor.redColor()
                }
            }
        }

But if you want it to be change in whole app and targeting the iOS 9.0 or later then should be using appearanceWhenContainedInInstancesOfClasses like

UITextField.appearanceWhenContainedInInstancesOfClasses([UISearchBar.self]).backgroundColor = UIColor.redColor()
Stephine answered 17/11, 2015 at 7:44 Comment(1)
I do not know why, but it still doesn't change the colorRespiratory
L
16

I did one UISearchBar extension & category for customize text filed within search bar.

Compatible from iOS 9 to iOS 13.

Swift 4+

import UIKit

extension UISearchBar {

    // Due to searchTextField property who available iOS 13 only, extend this property for iOS 13 previous version compatibility
    var compatibleSearchTextField: UITextField {
        guard #available(iOS 13.0, *) else { return legacySearchField }
        return self.searchTextField
    }

    private var legacySearchField: UITextField {
        if let textField = self.subviews.first?.subviews.last as? UITextField {
            // Xcode 11 previous environment
            return textField
        } else if let textField = self.value(forKey: "searchField") as? UITextField {
            // Xcode 11 run in iOS 13 previous devices
            return textField
        } else {
            // exception condition or error handler in here
            return UITextField()
        }
    }
}

Usage Example:

var searchController: UISearchController?
searchController?.searchBar.compatibleSearchTextField.textColor = UIColor.XXX
searchController?.searchBar.compatibleSearchTextField.backgroundColor = UIColor.XXX

Objective-C

UISearchBar+SearchTextField.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface UISearchBar (SearchTextField)

// Due to searchTextField property who available iOS 13 only, extend this property for iOS 13 previous version compatibility
@property (nonatomic, readonly) UITextField *compatibleSearchTextField;

@end

NS_ASSUME_NONNULL_END

UISearchBar+SearchTextField.m

#import "UISearchBar+SearchTextField.h"

@implementation UISearchBar (SearchTextField)

- (UITextField *)compatibleSearchTextField {
    if (@available(iOS 13.0, *)) {
#ifdef __IPHONE_13_0
        return self.searchTextField;
#else
        // Xcode 11 run in iOS 13 previous devices
        return (UITextField *)[self valueForKey:@"searchField"];
#endif
    } else {
        // Xcode 11 previous environment
        return [[[self.subviews firstObject] subviews] lastObject];
    }
}

@end

Usage Example:

- (UISearchBar *)searchBar {
    if (!_searchBar) {
        _searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(X, X, X, X)];
        _searchBar.compatibleSearchTextField.textColor = [UIColor XXX];
        _searchBar.compatibleSearchTextField.backgroundColor = [UIColor XXX];
    }
    return _searchBar
}

Locution answered 23/9, 2019 at 17:38 Comment(0)
D
13

Swift 5:

    searchController.searchBar.searchTextField.backgroundColor = .white
Deemphasize answered 14/11, 2019 at 2:18 Comment(3)
This should be the accepted answer. 1 line and worked perfectly and as expected. Nothing fancy and no workarounds. The best answer on this threadLowborn
This will crash under iOS 12.x which is why the other answers are more appropriate.Chorion
Using this with iOS 16 with no crashes.Phenacetin
T
12

The way to do this only using Apple APIs is to create an image and use setSearchFieldBackgroundImage:

self.searchBar.setSearchFieldBackgroundImage(UIImage(named: "SearchFieldBackground"), for: UIControlState.normal)

It will even animate the corners properly if you create a rounded rect and dynamically show and hide buttons.

Example using this image: enter image description here

enter image description here

Trinidadtrinitarian answered 12/1, 2017 at 8:45 Comment(4)
This is the same as just setting backgroundColor on the searchBar. Just unnecessarily complicated and doesn't solve the tint problem, because you can't change the text tint or text field background properly to match the backgroundNainsook
backgroundColor does not change anything for meAgogue
It's not unnecessarily complicated, it's the correct API to use.Thrashing
i m not able to change navigationItem bg color in ios 12. dsiplaying white all time. working fine in ios13. in my case want set that pink color.Mutazilite
B
11

You are adding the below code in ViewDidLoad and Change the textfield background color RED,

for subView in searchBar.subviews
{
    for subView1 in subView.subviews
    {

        if subView1.isKindOfClass(UITextField)
        {
            subView1.backgroundColor = UIColor.redColor()
        }
    }

}

Red Color of TextField in SearchBar.

enter image description here

Buttaro answered 17/11, 2015 at 7:38 Comment(3)
I do not know why, but I've tried many solutions and no one works for me =/Respiratory
above demo project Download and implement same as demo in your project.Buttaro
Un-check "Translucent" in search bar properties than above code will work.Ambience
D
10

For Swift 3+, use this:

for subView in searchController.searchBar.subviews {

    for subViewOne in subView.subviews {

        if let textField = subViewOne as? UITextField {

           subViewOne.backgroundColor = UIColor.red

           //use the code below if you want to change the color of placeholder
           let textFieldInsideUISearchBarLabel = textField.value(forKey: "placeholderLabel") as? UILabel
                textFieldInsideUISearchBarLabel?.textColor = UIColor.blue
        }
     }
}
Deckard answered 31/3, 2017 at 8:37 Comment(0)
W
9

I do it with this way(Swift 3+ solution):

let textFieldInsideSearchBar = searchBar.value(forKey: "searchField") as? UITextField
textFieldInsideSearchBar?.backgroundColor = UIColor.red
Wipe answered 15/5, 2017 at 15:1 Comment(1)
This is the only one that works in Xcode 11. Thanks!Elisaelisabet
E
9

Faced the same issue , for iOS 13+ , textFiled can be get by as follow

var searchText : UITextField?
if #available(iOS 13.0, *) {
   searchText  = searchBar.searchTextField
}
else {
    searchText = searchBar.value(forKey: "_searchField") as? UITextField
}
searchText?.backgroundColor = .red                                                              
Erose answered 7/11, 2019 at 12:46 Comment(1)
Nice answer. Simple and straight.Essayistic
N
9

Swift 5 extension:

Works perfect on all iOS versions

import UIKit

extension UISearchBar {

    func setupSearchBar(background: UIColor = .white, inputText: UIColor = .black, placeholderText: UIColor = .gray, image: UIColor = .black) {

        self.searchBarStyle = .minimal

        self.barStyle = .default

        // IOS 12 and lower:
        for view in self.subviews {

            for subview in view.subviews {
                if subview is UITextField {
                    if let textField: UITextField = subview as? UITextField {

                        // Background Color
                        textField.backgroundColor = background

                        //   Text Color
                        textField.textColor = inputText

                        //  Placeholder Color
                        textField.attributedPlaceholder = NSAttributedString(string: textField.placeholder ?? "", attributes: [NSAttributedString.Key.foregroundColor : placeholderText])

                        //  Default Image Color
                        if let leftView = textField.leftView as? UIImageView {
                            leftView.image = leftView.image?.withRenderingMode(.alwaysTemplate)
                            leftView.tintColor = image
                        }

                        let backgroundView = textField.subviews.first
                        backgroundView?.backgroundColor = background
                        backgroundView?.layer.cornerRadius = 10.5
                        backgroundView?.layer.masksToBounds = true

                    }
                }
            }

        }

        // IOS 13 only:
        if let textField = self.value(forKey: "searchField") as? UITextField {

            // Background Color
            textField.backgroundColor = background

            //   Text Color
            textField.textColor = inputText

            //  Placeholder Color
            textField.attributedPlaceholder = NSAttributedString(string: textField.placeholder ?? "", attributes: [NSAttributedString.Key.foregroundColor : placeholderText])

            //  Default Image Color
            if let leftView = textField.leftView as? UIImageView {
                leftView.image = leftView.image?.withRenderingMode(.alwaysTemplate)
                leftView.tintColor = image
            }

        }

    }

}
Neology answered 21/2, 2020 at 0:28 Comment(0)
C
6

Just like this

let searchBar:UISearchBar = UISearchBar(frame: CGRectMake((searchView.frame.width - UIScreen.mainScreen().bounds.width / 1.6) / 2, 0, UIScreen.mainScreen().bounds.width / 1.6, 24))
let searchTextField = searchBar.valueForKey("_searchField") as? UITextField
searchTextField?.backgroundColor = UIColor.redColor()
Confuse answered 17/11, 2015 at 8:27 Comment(0)
A
6

I was experimenting with the properties of searchBar and searchTextField when I found a solution to the above.

Below, I have listed the steps in order to achieve the desired result:

  1. Set the border style of the searchTextField to .none
  2. Set the background color of the searchTextField to your desired color
  3. Change the corner radius of the searchTextField's layer to 10
  4. Set the searchTextField's clipToBounds property to true

Further, I have provided the code below for your reference:

 let searchController = UISearchController(searchResultsController: nil)
 navigationItem.searchController = searchController

 searchController.searchBar.barTintColor = viewBackgroundColor
 searchController.searchBar.backgroundColor = viewBackgroundColor

 searchController.searchBar.searchTextField.borderStyle = .none
 searchController.searchBar.searchTextField.backgroundColor = .white
 searchController.searchBar.searchTextField.layer.cornerRadius = 10
 searchController.searchBar.searchTextField.clipsToBounds = true

Note: searchTextField is in Beta and available on iOS 13

Asylum answered 20/7, 2019 at 17:30 Comment(0)
R
6

Search Bar Color Change

Simply change the searchbar style to minimal and it will show the search bar's background color. To change the oval inside the box aka the textfield. Just change the searchbar.textfield.backgroundcolor attribute.

 searchbar.searchBarStyle = .minimal
 searchbar.backgroundColor = //color here                  
 searchbar.searchTextField.backgroundColor = //color here     
Response answered 19/6, 2021 at 16:2 Comment(0)
I
4

FWIW I'm solving this problem by creating a computed variable named textField.

extension UISearchBar {
    var textField: UITextField? {
        return subviews.first?.subviews.first(where: { $0.isKind(of: UITextField.self) }) as? UITextField
    }
}
Intimidate answered 17/8, 2017 at 15:52 Comment(0)
S
3

A very common answer to this question on the web is this solution described above:

for subView in searchBar.subviews {
    for subViewInSubView in subView.subviews {   
        if subViewInSubView.isKindOfClass(UITextField) {
            subViewInSubView.backgroundColor = UIColor.purpleColor()
       }
    }
}

But it didn't work for me using XCode 7 and iOS 9, and I noticed that around the web many others reported that it didn't work for them, either. I discovered that the UITextField subview isn't created (or at least it isn't added as a subview) until it is referenced, and one way it can be referenced is by the placeholder field, e.g., one could add this line before searching the subviews for the UITextField class:

searchBar.placeholder = searchBar.placeholder
Sibship answered 30/7, 2016 at 16:44 Comment(1)
Adding the placeholder before searching subviews made the difference for me, good catch!Hylo
M
2

Here's the solution:

func customizeSearchBar(){
    if let textfield = searchController.searchbar.value(forKey: "searchField") as? UITextField {
        textfield.textColor = UIColor.blue
        if let backgroundview = textfield.subviews.first {

            // Background color
            backgroundview.backgroundColor = UIColor.white

            // Rounded corner
            backgroundview.layer.cornerRadius = 10;
            backgroundview.clipsToBounds = true;
        }
    }
}

But Please note that this works only in iOS 11.0 and later. So don't forget to add before that

if #available(iOS 11.0, *) {}
Marylynnmarylynne answered 3/12, 2018 at 19:32 Comment(0)
H
2

For Swift 5 iOS 13+

The first line is to change the colour of the outside box colour and the second one is to change the colour of inside the search text box.

searchBar.barTintColor = .red
searchBar.searchTextField.backgroundColor = .white

Here is the output of the above code

Hamman answered 23/12, 2022 at 13:8 Comment(0)
M
1

Set any color you want. SWIFT 3

public extension UISearchBar {
  public func setStyleColor(_ color: UIColor) {
    tintColor = color
    guard let tf = (value(forKey: "searchField") as? UITextField) else { return }
    tf.textColor = color
    if let glassIconView = tf.leftView as? UIImageView, let img = glassIconView.image {
      let newImg = img.blendedByColor(color)
      glassIconView.image = newImg
    }
    if let clearButton = tf.value(forKey: "clearButton") as? UIButton {
      clearButton.setImage(clearButton.imageView?.image?.withRenderingMode(.alwaysTemplate), for: .normal)
      clearButton.tintColor = color
    }
  }
}

extension UIImage {

  public func blendedByColor(_ color: UIColor) -> UIImage {
    let scale = UIScreen.main.scale
    if scale > 1 {
      UIGraphicsBeginImageContextWithOptions(size, false, scale)
    } else {
      UIGraphicsBeginImageContext(size)
    }
    color.setFill()
    let bounds = CGRect(x: 0, y: 0, width: size.width, height: size.height)
    UIRectFill(bounds)
    draw(in: bounds, blendMode: .destinationIn, alpha: 1)
    let blendedImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return blendedImage!
  }
}
Mal answered 7/8, 2017 at 20:46 Comment(0)
S
1

A UISearchBar extension using Swift 4 based on the most voted answer

extension UISearchBar {

    func tfBackgroundColor(color: UIColor){
        for view in self.subviews {
            for subview in view.subviews {
                if subview is UITextField {
                    let textField: UITextField = subview as! UITextField
                    textField.backgroundColor = color
                }
            }
        }
    }
    }
Sur answered 8/3, 2019 at 14:3 Comment(0)
D
0

Just try your code as below in playground. If still that won't work, add more code to your question...

let searchView = UIView(frame: CGRect(x: 0.0,y: 0.0, width: 100, height: 50))

let searchBar:UISearchBar = UISearchBar(frame: CGRectMake((searchView.frame.width - UIScreen.mainScreen().bounds.width / 1.6) / 2, 0, UIScreen.mainScreen().bounds.width / 1.6, 24))

for subView in searchBar.subviews {
    for subViewInSubView in subView.subviews {   
        if subViewInSubView.isKindOfClass(UITextField) {
            subViewInSubView.backgroundColor = UIColor.purpleColor()
        }
    }
}
Diena answered 17/11, 2015 at 8:3 Comment(0)
I
0

I just came to share the ONLY way I could change the background color for the searchbar textField because I havent seen it on any answer yet, and none of the other suggestions, here or the in other sites, have worked for me.

  • Get the textField from the search bar, like the answer from @Steve ... anything works here as long as you get the textField. This was not my problem, the thing is, it did not metter the colors I setted here, it was not working extension UISearchBar { var textField: UITextField? { return subviews.first?.subviews.first(where: { $0.isKind(of: UITextField.self) }) as? UITextField } }

  • Make a new layer with the size of the navigationBar let layer = CALayer() layer.backgroundColor = UIColor.white.withAlphaComponent(0.5).cgColor //Set your color here layer.frame = navigationBar.frame

  • Set the new layer as sublayer for textfield navigationBar.textField?.layer.masksToBounds = true //to make sure you get the rounded corners navigationBar.textField?.layer.cornerRadius = 14 //Round it as you wish navigationBar.textField?.layer.addSublayer(layer)
  • thats it, you will have an rounded textField background with any color you want.
Inflation answered 14/8, 2018 at 1:3 Comment(0)
A
0

Here's the solution

func configureSearchBar() {
    for textField in searchBar.subviews.first!.subviews where textField is UITextField {
        textField.backgroundColor = .cyan
    }
}
Auric answered 30/1, 2019 at 8:26 Comment(0)
T
0

For 2024, the three colors you need to change:

class UsableUISearchBar: UISearchBar {
    
    override init(frame: CGRect) {
        
        super.init(frame: frame)
        common()
    }

    required init?(coder aDecoder: NSCoder) {
        
        super.init(coder: aDecoder)
        common()
    }

    func common() {
        barTintColor = .clear
        searchTextField.backgroundColor = .darkGray
        searchTextField.leftView?.tintColor = .white
    }
}
Tuinal answered 5/2, 2024 at 20:29 Comment(8)
Why 2024? Wasn't this solution valid in 2023? Wouldn't it be better to state what versions of iOS this works with?Patrick
@Patrick - all fair questions. (1) all answers could be improved. (2) "2024" means "In 2024, this is what you do." In other words "If you are reading this and it is 2024 [ie, the answer has not aged many years] this is what you do." (3) There are no time travelers. (4) I have zero interest in historic issues, and very few / realistically zero readers have interest in historic issues. (5) "Wouldn't it be better to state what versions of iOS this works with?" Yes and no: (a) I do not have the skill to do that. (b) It would wildly confuse a "give me a simple answer" type question. You would..Tuinal
..probably agree that of all the millions of users on this site, few users enjoy a "long complicated theoretical research-level discussion" QA more than me :) Many questions are like that. But many questions are just about the sewer of ephemera that is UIKit .. if someone needs to know "how the hell to set the color on..." a brief answer is best. Furthermore, as a philosophical point (c) the whole concept of having to make apps for clients that support older versions of iOS is becoming more and more historic every year; only truly huge-user-base apps now want anything more than the..Tuinal
But many apps support versions of iOS besides the latest. What if I need to support back to iOS 14 (or 15 or 16) in 2024? What if I'm reading this answer in November 2024. Does your answer apply to iOS 17 or iOS 18? Just a few issues with simply stating "2024". Besides, anyone can see when you posted the answer. Adding the year in the post doesn't help in any way.Patrick
.. most recent say three iOS, IMO. It's like, of a question like this, if - incredibly - someone compellingly needed to know the deets of how to achieve this on some very old iOS, that would be "a question in itself" - you know? A specialized question. Yes, 10-15 yrs ago on this site, EVERYTHING about iOS had to be tediously spoken of in terms of exact versions; today (IMO) that is much less or really no longer the case. (This has happen to droid, somewhat, even, these last few years.) (6) An overwhelming and central problem on SO is ...Tuinal
.. that (as you'd expect with software) most answers over a few yrs old should just be deleted and are useless. In many cases there are dozens of shoddy answers, AND, many/most are out of date and wrong. {Even the "relatively recent" answer by Muhammad here, is useless, it doesn't show you how to subclass UISearchBar to use the key info, and there's a color missing it's useless without.} Typing a heading like "IGNORE ALL THE CRAP ON HERE, HERE IS AN ACTUAL FULL USABLE UP TO DATE ANSWER" ... IMO tagging it with the current year essentially does that. That's my take.Tuinal
To repeat myself, "But many apps support versions of iOS besides the latest." Not so. 100,000+ apps are added every month. 99,500 are hobbyist crap and the learner programmer wouldn't even know what "version" means, they just open Xcode. Of serious apps only (as I discussed) the very largest care about more than say two old versions, these days, IMO. What if I need to support back [a bit] ... IMO "tagging" it this way, the implication is clear that it's good for the current iOS and back a couple. "Adding the year in the post doesn't help..." a large headline draws attention, it ..Tuinal
.. shouldn't have to be that way, but it is. Voting and "date modified" and the "tick" concept on SO are all crap. On hard questions, I look for the answer written by the person i know is most knowledgeable (often you!) On "trivia" questions like this, I look for the one that is freshest and gives the sense that the writer knows it ha sto work on current. (Exactly like Muhammad's "For Swift 5 iOS 13+" - which should have been in huge letters :) :) ) Those my thoughts I'm afraid !Tuinal

© 2022 - 2025 — McMap. All rights reserved.