How to change background color of the text field in the UISearchController?
Asked Answered
C

11

8

How to change the default grey background at UISearchController search text field?

Screen shot

Corbin answered 13/12, 2018 at 13:6 Comment(10)
see this #52905871Cheap
@wings what happens when Apple decides to change the view heirarchy?Cynth
Please see this answer: #52871177Countercheck
@RakeshaShastri... I don't understand :DCheap
@SagarChauhan what happens when Apple decides to change the key?Cynth
@RakeshaShastri, It will not change key now, and if there are any changes then it will not effect on live app. On new version you can change that key as per apple will decide.Countercheck
@SagarChauhan yea, but they won't tell you the new key. Just because you know it now doesn't mean you will know the new one. Also, if Apple does change the key, it will affect the live app. You cannot code for an OS that hasn't been released.Cynth
@RakeshaShastri, Ohh, Suppose, the old app have flatMap function and that is live now. So apple has been updated function name as compactMap, So it is effecting live app. Right ?Countercheck
@SagarChauhan wat?! no it doesn't. why would it affect live apps?! Either you're not explaining your point properly (which can happen, no big deal) or you're severely mistaken about how all of this works (which would be a rather big deal)...Garnet
share SearchController source codeSanborne
O
15

Here is a an example on how to set the textField background.

class ViewController: UIViewController {

    let searchController = UISearchController(searchResultsController: nil)

    private lazy var searchTextField: UITextField? = { [unowned self] in
        var textField: UITextField?
        self.searchController.searchBar.subviews.forEach({ view in
            view.subviews.forEach({ view in
                if let view  = view as? UITextField {
                    textField = view
                }
            })
        })
        return textField
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        searchController.obscuresBackgroundDuringPresentation = false
        searchController.searchBar.placeholder = "Search Candies"
        navigationItem.searchController = searchController
        definesPresentationContext = true

        if let bg = self.searchTextField?.subviews.first {
            bg.backgroundColor = .green
            bg.layer.cornerRadius = 10
            bg.clipsToBounds = true
        }
    }
}

Result

enter image description here

Ongoing answered 16/12, 2018 at 5:33 Comment(1)
Not the best way to find UITextField. Make it recursive at least. :(Jelks
C
7

To update background of UISearchController proper way is change background image.

If you see UISearchController in visual debugger you can find out that background of it is UIImageView:

enter image description here

So you should make small image of your search bar and set it to seachBar like this:

    lazy var searchController: UISearchController = {

        let searchController = UISearchController(searchResultsController: nil)

        searchController.searchBar.placeholder = "Search"
        searchController.searchBar.tintColor = UIColor.black
        searchController.searchBar.searchBarStyle = .minimal
        // Set background image to searchBar so it will resize
        searchController.searchBar.setSearchFieldBackgroundImage(UIImage(named: "oval_static"), for: .normal)

        definesPresentationContext = true

        return searchController
    }()

The image of searchBar (in project I recommend use .pdf or .png format of image here just screenshot):

enter image description here

The UISearchBar will resize it as need it and result is:

enter image description here

Moreover we can do something like this to create custom background just in code:

/// Just random extension to make image from UIView, you can use your own
extension UIView {

func asImage() -> UIImage {
    let renderer = UIGraphicsImageRenderer(bounds: bounds)
    return renderer.image { rendererContext in
        layer.render(in: rendererContext.cgContext)
    }
}}

lazy var searchController: UISearchController = {

        let searchController = UISearchController(searchResultsController: nil)

        searchController.searchBar.placeholder = "Search"
        searchController.searchBar.tintColor = UIColor.black
        searchController.searchBar.searchBarStyle = .minimal

        // Create own view with custom properties
        // Default height is 36 points
        let differentColorSearchBar = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 36))

        differentColorSearchBar.layer.cornerRadius = 8
        differentColorSearchBar.clipsToBounds = true
        differentColorSearchBar.backgroundColor = UIColor.blue

        searchController.searchBar.setSearchFieldBackgroundImage(differentColorSearchBar.asImage(), for: .normal)

        definesPresentationContext = true

        return searchController
    }

The Result is (of course you can change another properties of searchBar to make it better, but I just show you how change background properly):

enter image description here

I recommend avoid private properties just use open! Hope it's help.

Ceolaceorl answered 18/12, 2018 at 16:27 Comment(0)
A
2

On iOS13 and later, searchTextField is a member of UISearchBar. So you can use something like this:

searchController.searchBar.searchTextField.backgroundColor = UIColor.blue

Be careful, apple does not have proper notation in SDK showing that this property introduced in iOS 13, so if you are supporting iOS 12 or older it does not show you any warning. Make sure to wrap it for iOS 13 only.

Abstractionist answered 29/12, 2019 at 1:12 Comment(0)
B
1

I do it in this way, Objective-C code:

UITextField *searchField = [_navigationSearchBar valueForKey:@"searchField"];
searchField.backgroundColor = [UIColor defaultSeacrhBarColor];
searchField.textColor = [UIColor defaultWhiteColor];
searchField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:searchTitle];
UILabel *placeholderLabel = [searchField valueForKey:@"placeholderLabel"];
placeholderLabel.textColor = [UIColor lightTextColor];

UIButton *clearButton = [searchField valueForKey:@"clearButton"];
[clearButton setImage:[clearButton.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal];
clearButton.tintColor = [UIColor defaultWhiteColor];

_navigationSearchBar.delegate = self;
[_navigationSearchBar setTranslucent:NO];
[_navigationSearchBar setBackgroundImage:nil];
[_navigationSearchBar setBarTintColor:[UIColor defaultNavigationBarColor]];
[_navigationSearchBar setBackgroundColor:[UIColor defaultNavigationBarColor]];
[_navigationSearchBar setImage:[UIImage imageNamed:@"Search_Icon"] forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];
_navigationSearchBar.clipsToBounds = YES;
[_navigationBar addSubview:_navigationSearchBar];
Boone answered 19/12, 2018 at 14:52 Comment(0)
P
1

Max use this below function for changing color.

extension UISearchBar {
  func setBackgroundColor(){
    if let view:UIView = self.subviews.first {
        for curr in view.subviews {
            guard let searchBarBackgroundClass = NSClassFromString("UISearchBarBackground") else {
                return
            }
            if curr.isKind(of:searchBarBackgroundClass){
                if let imageView = curr as? UIImageView{
                    imageView.backgroundColor = .red
                    break
                }
            }
        }
    }
  }
}

Use this function with searchbar.

searchBarController.searchBar.setBackgroundColor()
Paneling answered 20/12, 2018 at 10:5 Comment(0)
U
1

In iOS 12 and below there is a need to cover the image inside the textfield, that image gives the background color we want to change. You can add a custom view at index 1 right after the imageview to achieve what you wanted.

if #available(iOS 13.0, *)
    {
        searchBar.searchTextField.textColor       = .black
        searchBar.searchTextField.backgroundColor = .red
    }
    else if let textFieldInsideSearchBar = searchBar.value(forKey: "searchField") as? UITextField
    {
        textFieldInsideSearchBar.textColor = .black
        let backgroundView = UIView(frame: textFieldInsideSearchBar.bounds)
        backgroundView.backgroundColor = .red
        backgroundView.layer.cornerRadius = 10
        backgroundView.clipsToBounds = true
        textFieldInsideSearchBar.insertSubview(backgroundView, at: 1)
    }
Unduly answered 17/12, 2020 at 18:33 Comment(0)
C
0

Apple has key 'searchField' to detect textfield in searchBar. So first safely get that textfield and do the change whatever you want with textfield.

let searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.searchBar.placeholder = "Search here..."
searchController.searchBar.delegate = self
searchController.searchBar.tintColor = .white
searchController.searchBar.barTintColor = .white
searchController.hidesNavigationBarDuringPresentation = false
searchController.obscuresBackgroundDuringPresentation = false

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

    // Set text colour of text field   
    textfield.textColor = UIColor.blue

    if let backgroundview = textfield.subviews.first {

        // Get background view and change background color
        backgroundview.backgroundColor = UIColor.white

        // Set rounded corner
        backgroundview.layer.cornerRadius = 10
        backgroundview.clipsToBounds = true
    }
}

if #available(iOS 11.0, *) {
    self.navigationItem.searchController = searchController
} else {
    self.tblCustomers.tableHeaderView = searchController.searchBar
}

This is working code and I have implemented in my current project. Still if you have any query then let me know.

I hope this will help you.

Colugo answered 20/12, 2018 at 4:47 Comment(3)
When you write .value(forKey: "searchField"), you are calling Apple to reject your app anytime they notice. Also, your app is going to crash if they just rename the searchField attribute in any new version.Ongoing
@Kamran, First of all, I have safely getting textField by optional unwrap by if let, So it will not crash app. Second thing, If app is live then how will it crash. Also, one of my app already live where this code is available.Colugo
Yeah, optional unwrap will work if this .value(forKey: "searchField") doesn't crash. If it crashed inside this method, optional unwrap can not save you. If app is live and they renamed the attribute in new os then it will start crashing as this key will not be available. Lastly, your app and many other apps are live because Apple didn't notice that you are accessing a private api. Anytime they notice this, they can reject the app.Ongoing
C
0

There is no any proper/public way for changing this searchbar's background color. There are some ways by using private apis, like answer by @sanjayshah, but in that case, there are chances that apple might reject your application. I think you should move on using default background color. Most of the apps use the same.

Caritacaritas answered 21/12, 2018 at 5:38 Comment(0)
M
0

A recursive version of @Kamran's answer with a better best-case and average running time. The accepted version does not work on iOS 13+ for me.

private lazy var searchTextField: UITextField? = { [unowned self] in
    guard let searchBar = self.searchController?.searchBar else { return nil }
    var views =  searchBar.subviews
    while !views.isEmpty {
        guard let view = views.popLast() else { break }
        if let textfield = view as? UITextField {
            return textfield
        }
        views += view.subviews
    }
    return nil
}()
Maximilian answered 11/8, 2019 at 20:48 Comment(0)
D
0

First Check the Platform,

than make the modification, cause IOS 13 dosen't accept a lot of tricks made for IOS 12

if #available(iOS 13, *) {
   searchController.searchBar.searchTextField.backgroundColor = .white 
} else {

for textField in searchController.searchBar.subviews.first.subviews where   textField is UITextField {
textField.subviews.first.backgroundColor = .white
textField.subviews.first.layer.cornerRadius = 10
textField.subviews.first.layer.masksToBounds = true
  }
}
Demakis answered 17/9, 2020 at 12:28 Comment(0)
I
-4

Did you try something like

searchController.searchBar.backgroundColor = UIColor.blue
Ilysa answered 13/12, 2018 at 14:39 Comment(1)
Okay! Maybe you can try with subviews inside of searchBar and if you find a subview that is a UITextField change its backgroundColorIlysa

© 2022 - 2024 — McMap. All rights reserved.