UISearchBar cancel button color?
Asked Answered
C

11

43

When I drop a UISearchBar into my view inside Interface Builder, and change its style to Black Opaque, the cancel button stays unfittingly blue / gray and doesn't become black.

How can I make the cancel button black?

EDIT: It does work like this:

// Assume a UISearchBar searchBar.
NSArray *subviews = [searchBar subviews];

// The index depends on how you configure the searchBar.
UIButton *cancelButton = [subviews objectAtIndex:3];

// Set the style to "normal" style.
[cancelButton setStyle:0];

But the setStyle: method is from a private framework, so this might be an issue when submitting the app to Apple.

Calorimeter answered 7/5, 2010 at 9:22 Comment(1)
instead of using [canelButton setStyle:0] use cancelButton.tintColor=[UIColor blackColor];Lias
K
120

I used some thing like this and worked with me:

[[UIBarButtonItem appearanceWhenContainedIn: [UISearchBar class], nil] setTintColor:[UIColor blackColor]];

it changed the cancel button color to black.

Update for iOS 9.0, the method appearanceWhenContainedIn is deprecated, use appearanceWhenContainedInInstancesOfClasses instead:

[[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTintColor:[UIColor blackColor]];

And in Swift 3:

UIBarButtonItem.appearance(whenContainedInInstancesOf:[UISearchBar.self]).tintColor = UIColor.black
Kalfas answered 3/4, 2013 at 15:8 Comment(7)
Deprecated in iOS 9: apple doc. Solution: #24137374Farrahfarrand
Not really working on iOS 9. The button color stays the same.Up
What's with this up vote madness? Set tintColor, job doneSingultus
@AdamWaite tintColor changes both the cursor and "Cancel" button color.Nut
@ChaitanyaShah just set the searchBar tintColor to the desired "Cancel" button color, and UITextField's appearanceWhenContainedIn... to another colorTiphanie
Swift 3: UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).tintColor = UIColor.blackPlunger
This is not working if set after creating instance of UISearchBarRoom
M
36

The problem with your solution is that the code is assuming that the objectAtIndex:3 is the cancel button. Not only does this generate a compiler warning, but also if you are displaying the Cancel button programmatically (for example using [searchBar setShowsCancelButton:YES], you risk crashing the application.

A simpler solution is to set the style of the whole search bar in ViewDidLoad(), using:

searchBar.tintColor = [UIColor colorWithWhite:0.3 alpha:1.0];

this overrides the style set in the Interface Builder BUT also changes the colour of the Cancel button to be same colour as the whole bar (although it doesn't let you set the style of Cancel button independently, unfortunately.

Medawar answered 7/9, 2010 at 11:43 Comment(1)
We can also change the color of the cancel button independently irrespective of the color of the searchbar. searchBar=[[UISearchBar alloc]initWithFrame:CGRectMake(10,346,300,0)]; searchBar.tintColor=[Reusables SKColorFromHexString:@"#505a62"]; searchBar.delegate=self; searchBar.showsCancelButton=YES; NSArray *subviews = [searchBar subviews]; // The index depends on how you configure the searchBar. UIButton *cancelButton = [subviews objectAtIndex:2]; cancelButton.tintColor=[UIColor lightTextColor];Lias
A
9

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

@IBOutlet weak var sbSearchBar: UISearchBar!

sbSearchBar.showsCancelButton = true
sbSearchBar.barTintColor = UIColor.blue
sbSearchBar.tintColor = UIColor.red

if let buttonItem = sbSearchBar.subviews.first?.subviews.last as? UIButton {
    buttonItem.setTitleColor(UIColor.yellow, for: .normal)
}

enter image description here

Abilene answered 15/3, 2018 at 14:31 Comment(1)
Hi, I think you should use first(where:) to find the UINavigationButton ``` if let cancelItem = searchBar.subviews.first?.subviews.first(where: { $0 is UIButton }) as? UIButton { cancelItem.setTitleColor(UIColor.black, for: .normal) } ```Chaldea
G
7

In Swift 4.2

let appearance = UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self])
appearance.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor(named: "goldColor")!], for: .normal)

This works for me. Thanks @Tim Semple

Groschen answered 28/11, 2018 at 7:3 Comment(0)
H
6

for iOS 10:

UISearchBar.appearance().tintColor = UIColor.red //cancel button color
UISearchBar.appearance().barTintColor = UIColor.blue //background button color
Hilburn answered 8/5, 2017 at 12:33 Comment(1)
Putting this in AppDelegate.application() sets it globally for your app, which is perfect for me. Simple and effective.Madriene
A
4

This is an updated version of Hossam Ghareeb's answer above for Swift 3:

UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self] ).tintColor = UIColor.red

But this will not override appearance if it has already been set elsewhere for UIBarButtonItem.

For example, in my navbar controller I had to change this:

UIBarButtonItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName:UIColor.white], for: UIControlState.normal)

To this for the solution above to work:

UIBarButtonItem.appearance(whenContainedInInstancesOf: [UINavigationBar.self] ).setTitleTextAttributes([NSForegroundColorAttributeName:UIColor.white], for: UIControlState.normal)
Atchley answered 13/2, 2017 at 12:46 Comment(0)
S
2

Came up with a following solution and it is working on iOS 13.0 and iOS 12.4 as well, must be working on prior versions to till iOS 9.0. The following solution is for:

  1. Cancel Button Color (Normal State).
  2. Cancel Button Color (Disabled State).
  3. Search Bar Text Field Background Color (Normal State).

For Objective C:

[[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTintColor:[UIColor whiteColor]]; 

[[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor whiteColor]} forState:UIControlStateNormal];

[[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor whiteColor]} forState:UIControlStateDisabled];

[[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTitleTextAttributes:@{NSBackgroundColorAttributeName: [UIColor whiteColor]} forState:UIControlStateNormal];

The above code also fixed my UI issues for iOS 13 and iPhone X. I included this code in my AppDelegate.m class in didFinishLaunchingWithOptions function, so that the changes could be done in the whole app.

Sublimity answered 7/1, 2020 at 12:33 Comment(0)
S
1

I have taken Benjamin's answer and combined it with safe Array lookup to produce a short, but safe functional version:

searchController.searchBar.tintColor = UIColor.whiteColor()
(searchController.searchBar.subviews[safe: 0]?.subviews as? [UIView])?
    .filter({$0.isKindOfClass(UITextField)})
    .map({$0.tintColor = .lightGrayColor()})

This results in coloring the Cancel button white and the cursor when typing gray. Otherwise it would be white and thus not seen. The searchController is an object of type UISearchController. If anybody wants to use it inside the results controller, replace it with self.

The implementation of the safe: subscript is nkukushkin's answer:

extension Array {
    subscript(safe index: Int) -> T? {
        return indices(self) ~= index ? self[index] : nil
    }
}
Sequacious answered 10/9, 2015 at 11:28 Comment(0)
A
1

Click on Search bar and set the tint color under view from Interface Builder.

enter image description here

Atelier answered 21/10, 2016 at 9:43 Comment(0)
N
1
let view: UIView = self.searchBar.subviews[0] as UIView
let subViewsArray = view.subviews

for subView: UIView in subViewsArray {
    if let cancelButt = subView as? UIButton{
        cancelButt.setTitleColor(UIColor.white, for: .normal)         
    }
}

This worked for me

Neoplasm answered 31/12, 2016 at 22:24 Comment(0)
L
0

For those looking to reproduce the same behavior in Swift :

override func viewWillAppear(animated: Bool) {
    self.searchBar.tintColor = UIColor.whiteColor()

    let view: UIView = self.searchBar.subviews[0] as! UIView
    let subViewsArray = view.subviews

    for (subView: UIView) in subViewsArray as! [UIView] {
        println(subView)
        if subView.isKindOfClass(UITextField){
            subView.tintColor = UIColor.blueColor()
        }
    }

}
Lyophilize answered 14/4, 2015 at 14:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.