I have a UISearchBar that has a cancel button (it's displayed using -(void)setShowsCancelButton:animated). I've changed the tintColor of the search bar like this in an attempt to get a grayish searchbar:

14 Answers
14

What you want to do is pretty tough. There is no built-in hook to get at the cancel button.

However, there are a couple of options if you are willing to jimmy open the hood.

First off, UISearchBar is a UIView, and the Cancel button is also a view, which is added into the search bar as a subview, just as you would expect.

I have experimented a little, and can tell you that when the button is onscreen it has a size of 48,30.

So in viewWillAppear, you can do something like this:

Find the cancel button view in [searchBar subviews] by looking for one with size 48,30. (There only seems to be one -- this could change...) You could be doubly careful and look for one that is in approximately the correct position (differs in landscape and portrait).

Add a subview to the cancel button.

The subview should be a UIControl (so that you can set enabled = NO, in order to make sure touch events get to the actual cancel button)

It needs to have the right color and rounded corners; you will need to fudge the size for reasons I don't yet understand (55,30 seems to work)

This will work if searchBar.showsCancelButton is always YES; if you want it to disappear when not editing the search string, you will need to find a hook to add the overlay each time the cancel button appears.

As you can see, this is some ugly tinkering. Do it with eyes wide open.

I was hoping it wouldn't come to something like this :) It does work the way you described (except the size of the cancel button is somehow 55x30 for me). Still need to play around with getting the look right but it probably works, other than the ugliness of this approach. Thanks a lot for your help!
–
Chu YeowJul 29 '09 at 17:19

Hmm! All I'd like to do is change the tintColor of the Scope Button bar. Perhaps something similar would get me that view too ... but it's so fragile. Yecch. Decisions decisions.
–
Joe D'AndreaAug 31 '09 at 2:13

jandrea -- put up your own question and point me to it -- I'll try to explain how to do something similar.
–
AmagrammerAug 31 '09 at 15:34

This is not a good idea. The width of the cancel button will change depending on the users language setting, as "cancel" in other languages will be longer or shorter.
–
DermotJun 12 '12 at 11:30

Though this might not be exactly relevant to the original question, the solution is still applicable in the larger sense of trying to customize the Cancel button in the UISearchBar. Thought this will help others who are stuck in such a scenario.

My situation was to change the cancel button's title, but with a twist, wherein I did not want to show the cancel button by default but only wanted it to show up, when the user enters the search mode (by clicking inside the search text field). At this instant, I wanted the cancel button to carry the caption "Done" ("Cancel" was giving a different meaning to my screen, hence the customization).

Nevertheless, here's what I did (a combination of caelavel's and Arenim's solutions):

This gives a warning that cancelButton may not respond to setTintColor since this is an undocumented API. This also likely gets your app refused by Apple for using an undocumented API.
–
BenoitOct 20 '10 at 19:01

I'll give a detailed answered regarding the UIAppearance technique. First, you need to understand that the cancel button is a private UINavigationButton:UIButton. After some inspection, it appears that UINavigationButton will respond to those UIAppearance selectors:

Keep in mind you should only access this when the Cancel button is visible because UISearchBar seems to create a new button object every time it shows. Don't save the pointer to the cancelButton, just get it when needed: