52

I want to change the color of the text and icon in the iOS 11 searchbar when it is embedded in the navigation bar. So placeholder text, search text and search icon.

enter image description here

if #available(iOS 11.0, *) {
    navigationController?.navigationBar.prefersLargeTitles = false
    let searchController = UISearchController(searchResultsController: nil)
    navigationItem.searchController = searchController
    navigationItem.hidesSearchBarWhenScrolling = false

    searchController.searchBar.placeholder = "Suchen"
    searchController.searchBar.tintColor = .white
}

As you can see in the image, the text is grey on a deep blue background, which looks ugly. I want to text and icon to be at least white. (changing the blue background color also does not work really good, see my other question)

The only thing which works is changing the color of the blinking cursor and the "cancel" button, which is done with the .tintColor property.

Solutions which seems to work in iOS 10 and below seem not work anymore in iOS 11, so please post only solutions which you know working in iOS 11. Thanks.

Maybe I miss the point about this "automatic styling" in iOS 11. Any help is appreciated.

Darko
  • 9,655
  • 9
  • 36
  • 48

8 Answers8

122

I just found out how to set also the rest of them: (with some help of Brandon, 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]

Thanks for the help @Brandon!

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:

let searchController = UISearchController(searchResultsController: nil)
searchController.delegate = self

let searchBar = searchController.searchBar
searchBar.tintColor = UIColor.white
searchBar.barTintColor = UIColor.white

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

if let navigationbar = self.navigationController?.navigationBar {
    navigationbar.barTintColor = UIColor.blue
}

navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = false

enter image description here

Taken from here.

Benjohn
  • 13,228
  • 9
  • 65
  • 127
Darko
  • 9,655
  • 9
  • 36
  • 48
  • 7
    Awesome stuff, very helpful --- However, I'm having a problem with the background color, the white background of the field. If you sample it, it is not actually white, it's rgb(.95,.95,.95). Turns out, that `textField.subviews.first` view has its own subviews, which apply alpha-tinted shading. I've tried everything short of swizzling to kill those shaders, no luck. If anyone finds a fix, would love to hear it – beebcon Oct 07 '17 at 22:16
  • 1
    Regarding ^^ I finally found a fix. After the search bar `didMoveToSuperview`, if you go `for subview in textField.subviews.first.subviews` `subview.removeFromSuperview()` it seems you can eliminate the shaders, and get a pure white background rgb(1,1,1) – beebcon Oct 07 '17 at 22:24
  • @beebcon have either of you fixed this on iOS 11.2 where the text when typed is coloured white so is invisible? – simonthumper Jan 17 '18 at 16:21
  • not sure if anyone has come across this, but it seems like the searchbar background color defaults to black unless it is given one of the UIColor enums as a value – sanch Apr 02 '18 at 02:02
  • 1
    So I have a custom color (it's a shade of gray) and it kept appearing as black. I was going to use the above solution but it removed my custom color altogether (although it wouldn't if I set the background to white...which makes no sense). So I set out to have a bottom border (like material design search bar) since my search bar blended in with the nav bar and all the sudden, BOOM my proper custom gray showed up. Figured out if I set `tf.borderStyle = .none` it magically works. wow. – Michael McKenna Feb 07 '19 at 00:57
  • 1
    To change background color, no need to access a subview, simply do this: `if let textfield = scb.value(forKey: "searchField") as? UITextField { textfield.backgroundColor = UIColor.blue }` – rs7 Jun 23 '19 at 23:42
  • Isn't this using private api? Will apple approve this? – Bruno Muniz Jul 24 '19 at 19:13
  • 1
    @BrunoMuniz No, it‘s not a private API. But it implies knowledge of the inner workings of the navigation bar. Which means - it could stop working in a future iOS version. So you need to test it on iOS updates. – Darko Jul 25 '19 at 20:11
  • as @MichaelMcKenna says, but to keep the rounded corners and the exact color I want, then I needed to first set the borderStyle to .none and then immediately to .roundedRect in `viewDidLayoutSubviews` – Samuël May 19 '20 at 15:09
3

Put

UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [NSForegroundColorAttributeName: UIColor.white]

and

UISearchBar.appearance().tintColor = UIColor.white in the AppDelegate.

Alternatively, put them both in [UIViewController viewDidLoad:]

Brandon
  • 22,723
  • 11
  • 93
  • 186
  • This, does change the search text color, great! But the placeholder text color and icon is still missing. – Darko Sep 02 '17 at 03:18
  • 1
    Objective-C syntax: [UISearchBar appearance].tintColor = [UIColor whiteColor]; [[UITextField appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setDefaultTextAttributes:@{NSForegroundColorAttributeName: [UIColor whiteColor]}]; – Wayne Jan 03 '18 at 14:02
3

In addition to Darko's answer. In my case I need to get pure white search textfield color. Also I need a custom borderLine and cornerRadius. So if I just set background color to white, set custom corner radius and custom border line I've got something like this. Look at this ugly grey highLight when you tap on textfield

The problem is that the search bar has some subviews and I've just removed them. Here is my code:

@interface YourViewController () <UISearchBarDelegate, UISearchControllerDelegate>
// your properties
@property (nonatomic,strong) UISearchController *searchController;
@property (nonatomic,strong) UISearchBar *searchBar;
@end

- (void)viewDidLoad {
[super viewDidLoad];

_searchController = [[UISearchController alloc] initWithSearchResultsController:self.resultsTableController];
_searchController.delegate = self;
_searchController.searchBar.delegate = self;
_searchBar = self.searchController.searchBar;

if (@available(iOS 11.0, *)) {

    UITextField *searchTextField = [_searchBar valueForKey:@"searchField"];
if (searchTextField != nil) {
        searchTextField.layer.cornerRadius = 4.f;
        searchTextField.layer.borderWidth = 1.f;
        searchTextField.clipsToBounds = YES;

        for (UIView *subView in searchTextField.subviews) {
            [subView removeFromSuperview];
        }
}

// Color for "Cancel" button
    _searchBar.tintColor = [UIColor blackColor];
// Add searchController to navgationBar
    _navigationItem.searchController = _searchController;
// Hide searchBar when scroll
    _navigationItem.hidesSearchBarWhenScrolling = YES;
}
}

Now I've got a searchBar with pure white background, custom cornerRadius, custom border width. Also I've disabled grey highlight when tap. Editing searchfield Resign first responder

Alex Kolovatov
  • 859
  • 7
  • 12
2

Set Search Text Color

(UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]) ).defaultTextAttributes = [NSForegroundColorAttributeName: UIColor.white]

Set Search Placeholder Color

(UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]) ).attributedPlaceholder = [NSForegroundColorAttributeName: UIColor.white]
Donny
  • 189
  • 9
  • This one is great for the Search Text Color. Why does the solution to Change the Background not work for me? – jlstr Nov 22 '17 at 17:56
1

my two cents for Swift 4.x, lightly cleaned up.

Add in controller or App Delegate:

appearance.backgroundColor = .green
let myFont = UIFont.italicSystemFont(ofSize: 12)
let attribs = [
    NSAttributedString.Key(rawValue: NSAttributedString.Key.font.rawValue): myFont,
    NSAttributedString.Key(rawValue: NSAttributedString.Key.foregroundColor.rawValue): UIColor.red
]

appearance.defaultTextAttributes =  attribs

in controller:

self.searchBar.barTintColor = .blue

You will get Blue background, green search bar background, red italic font:

enter image description here

ingconti
  • 10,876
  • 3
  • 61
  • 48
0

I tried Daroko solution, but i had a problem when changing the background to pure white color (it’s was grey). My solution was to use the setSearchFieldBackgroundImage. also i don't want to rely on apple struct for getting the UITextField

  if #available(iOS 11.0, *) {
     let whiteImage = UIImage(color: UIColor.white, size: CGSize(width: searchController.searchBar.layer.frame.width, height: searchController.searchBar.layer.frame.height))
     searchController.searchBar.setSearchFieldBackgroundImage(whiteImage, for: .normal)
     self.navigationItem.searchController = searchController
     self.navigationItem.hidesSearchBarWhenScrolling = true
 }


public extension UIImage {
  public convenience init?(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) {
    let rect = CGRect(origin: .zero, size: size)
     UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
     color.setFill()
     UIRectFill(rect)
     let image = UIGraphicsGetImageFromCurrentImageContext()
     UIGraphicsEndImageContext()
     guard let cgImage = image?.cgImage else { return nil }
     self.init(cgImage: cgImage)
} }

I used UIImage extension from : Create UIImage with solid color in Swift

Gal Danay
  • 1
  • 1
0

In case someone gets stuck wondering why Darkos solution doesn't work, try changing the UINavigationBar's style to default instead of black. Took me half a day to figure out ¯\_(ツ)_/¯

CJiOS
  • 106
  • 1
  • 6
-4

This code changes the background color of the text field

Swift 4

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        //background color of text field
         UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).backgroundColor = .cyan

        }

edited: sample of a UISearchBar in cyan

sample

Maruta
  • 1,063
  • 11
  • 24