UISearchController iOS 11 Customization
Asked Answered
T

9

59

I had been using the following code prior to iOS 11 to customize the appearance of the UISearchController search bar:

var searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.setDefaultSearchBar()
searchController.searchResultsUpdater = self

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

extension UISearchBar {
    func setDefaultSearchBar() {
        self.tintColor = UIColor.blue
        self.searchBarStyle = .minimal
        self.backgroundImage = UIImage(color: UIColor.clear)
        let searchBarTextField = self.value(forKey: "searchField") as! UITextField
        searchBarTextField.textColor = UIColor.white
        searchBarTextField.tintColor = UIColor.blue
        searchBarTextField = .dark
    }
}

However, the appearance of the search bar fails to update when running the same code on iOS 11.

iOS 10:

enter image description here

iOS 11:

enter image description here

Much of the attention to this question so far has focused on the text color of the search bar. I am looking at more than this - the background color, tint color, the search indicator, clear button color, etc.

Tackling answered 13/8, 2017 at 17:43 Comment(9)
Well asked, but I cannot be surprised if, when you adopt the notion of the search field being handled through the navigation bar, the runtime imposes its own look upon it. You might be able to enforce your customizations by delaying them until after the runtime has had a chance to configure the search bar itself, but that's just a guess and it wouldn't surprise me if that didn't work either.Getupandgo
You can achieve that kind of customisation using appearance proxies. However, in my experience it was buggy - The bar looks exactly as I want it to at first, but when another view controller hides it, it loses the rounded corners.Abelmosk
Try apply font appearance to search field (white font color).Mean
Try by adding searchController.searchBar.tintColor = UIColor.white It should work.Yevetteyew
Which version of iOS11 are you using? Have you did a complete clean of the Project? It may be a bug of the OS. However I will try to reproduce it and give you feedback soon...! @NishantBhindi he already does it...Somatotype
I am using the latest beta version of iOS 11 @AndreaVultaggioTackling
try setting the navigationItem textColorBlakley
Post an example project on GitHub, maybe you will get some more help that way.Blakley
I have the same problems: #45998496Anachronistic
A
79

I just found out how to set them: (with some help of Brandon and Krunal, thanks!)

The "Cancel" text:

searchController.searchBar.tintColor = .white

The search icon:

searchController.searchBar.setImage(UIImage(named: "my_search_icon"), for: UISearchBarIcon.search, state: .normal)

The clear icon:

searchController.searchBar.setImage(UIImage(named: "my_search_icon"), for: UISearchBarIcon.clear, state: .normal)

The search text:

UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [NSAttributedStringKey.foregroundColor.rawValue: UIColor.white]

enter image description here

The placeholder:

UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).attributedPlaceholder = NSAttributedString(string: "placeholder", attributes: [NSAttributedStringKey.foregroundColor: UIColor.white])

enter image description here

The white background:

if #available(iOS 11.0, *) {
    let sc = UISearchController(searchResultsController: nil)
    sc.delegate = self
    let scb = sc.searchBar
    scb.tintColor = UIColor.white
    scb.barTintColor = UIColor.white

    if let textfield = scb.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;
        }
    }

    if let navigationbar = self.navigationController?.navigationBar {
        navigationbar.barTintColor = UIColor.blue
    }
    navigationItem.searchController = sc
    navigationItem.hidesSearchBarWhenScrolling = false
}

enter image description here

Taken from here.

Anachronistic answered 2/9, 2017 at 4:26 Comment(13)
Again this answer isn’t great with colors. They navigation bar background color always seems darker than with what you specify.Tackling
Hi @AlexanderMacLeod , did you fix it?Mastin
Should be advised that, like through all of iOS dev, using any value:forKey: is considered accessing private api waters and would be most likely against Apple's t&cBiplane
WHY DOES APPLE BREAK THINGS EVERY RELEASESurcease
This answer has almost saved me! Thanks! The only issue is that when you are pushing between view controllers, a black animated row appears instantly in the background of navigation area.Junji
@Junji Im having the same issue, did you find a quick fix for this?Mccullum
One issue with the white background code: a thin white line appears above the search field when pulling down the tableview. Does anyone has a solution for this?Mycorrhiza
@Mccullum unfortunately not, if you mean the "black animated row..." issue.Junji
@Junji it turned out to be the background color of a parent view. (this search bar was on a UIViewController set as a root of a UINavigationController inside of a UITabBarController)Mccullum
Another issue is the background color is not white but whiteish. I can't seem to get that changed in any way. Making my own implementation and living without the navigation integration.Rust
I found a solution for the whiteish. The solution is to use searchBar.setSearchFieldBackgroundImage(backgroundImage, for: .normal) with an image that is transparent. If anyone need a solution pm me and I'll add it.Rust
navigationbar.isTranslucent = false will also need for navigation barJunto
Best answer! Tried dozens of methods and only this one workedOgata
F
11

To properly set the text typed into the search bar to white use (when using a dark field color):

searchController.searchBar.barStyle = .black

To set the textfield background color

if #available(iOS 11.0, *) {

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

                // Background color
                backgroundview.backgroundColor = UIColor.white

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

However using something like

textfield.textColor = UIColor.blue

in the above does not seem to work.

Faye answered 4/12, 2017 at 10:57 Comment(0)
E
6

Try setting the search bar's bar style.

searchController.searchBar.barStyle = UIBarStyleBlack;

image 1

Elbaelbart answered 26/9, 2017 at 3:8 Comment(1)
Excellent! This switches the text colour from black to white.Bowerman
G
5

Moving the call to setDefaultSearchBar into viewDidAppear should fix this.

Grandiloquence answered 21/8, 2017 at 20:9 Comment(2)
This answer works with some properties like text color but not backgroundImage. It also leaves an ugly snap change when pushing between viewsTackling
@AlexanderMacLeod too bad but I guess you are right, it won't work for all props :(Grandiloquence
E
4

You need to find the UISearchBar's underlying UITextField and change its text color.

Notice this only have effect when search controller is going to present (UISearchControllerDelegate.willPresentSearchController) or presented.

class ViewController : UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // setup your search controller...

        // set search controller's delegate
        navigationItem.searchController?.delegate = self
    }
}

extension ViewController : UISearchControllerDelegate {

    func willPresentSearchController(_ searchController: UISearchController) {
        // update text color
        searchController.searchBar.textField?.textColor = .white
    }
}

extension UISearchBar {

    var textField: UITextField? {
        for subview in subviews.first?.subviews ?? [] {
            if let textField = subview as? UITextField {
                return textField
            }
        }
        return nil
    }
}
Emoryemote answered 24/8, 2017 at 9:51 Comment(1)
Thank you, you saved my day) It is really a challenge to customize UISearchBar in IOSBeverleybeverlie
G
3
    UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
Greengrocer answered 14/11, 2017 at 23:15 Comment(1)
Perhaps you could explain your answer a little more? Code-only answers are generally not the most useful.Ranson
C
2

Try it: searchController.<YOUR SEARCHBAR>.barStyle = .blackOpaque instead of self.searchBarStyle = .minimal.

Thus:

var searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.setDefaultSearchBar()
//Add this line below
searchController.searchBar.barStyle = .blackOpaque
searchController.searchResultsUpdater = self

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

extension UISearchBar {
    func setDefaultSearchBar() {
        self.tintColor = UIColor.blue
        //Delete this line below
        self.searchBarStyle = .minimal
        self.backgroundImage = UIImage(color: UIColor.clear)
        let searchBarTextField = self.value(forKey: "searchField") as! UITextField
        searchBarTextField.textColor = UIColor.white
        searchBarTextField.tintColor = UIColor.blue
        searchBarTextField = .dark
    }
}
Cordeliacordelie answered 14/4, 2018 at 14:10 Comment(0)
L
1

If you need to change the background colour of the textField in the searchBar, see my answer here: https://mcmap.net/q/331078/-wrong-placement-of-search-text-field-inside-search-bar-on-ios-11

Lithometeor answered 20/9, 2017 at 9:38 Comment(2)
Your answer doesn't work particularly well with colours - they always seem much darker than what you specify in codeTackling
Yes I know, but it's the best I could get. Let me know if you find a workaround.Lithometeor
H
0

You have to access the UITextField inside the UISearchBar. You can do that by using

let textFieldInsideSearchBar = yourSearchbar.value(forKey: "searchField") as? UITextField

textFieldInsideSearchBar?.textColor = yourcolor

OR

enter image description here

Harhay answered 24/8, 2017 at 4:17 Comment(1)
Probably You got clear tint color, it's the only reason I could imaging try to set "_searchBar.tintColor = [UIColor redColor];"Harhay

© 2022 - 2024 — McMap. All rights reserved.