21
votes

Is there any way to change the text font and color of the UISearchBar Cancel button without subclassing the searchbar?

11

11 Answers

73
votes

You can change Cancel button styling by changing the appearance of UIBarButtonItem when contained in UISearchBar.

For example,

[[UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
                                                      [UIColor blueColor], 
                                                      UITextAttributeTextColor, 
                                                      [UIColor darkGrayColor], 
                                                      UITextAttributeTextShadowColor, 
                                                      [NSValue valueWithUIOffset:UIOffsetMake(0, -1)], 
                                                      UITextAttributeTextShadowOffset,
                                                      nil] 
                                            forState:UIControlStateNormal];
19
votes

Swift 3

let attributes = [
    NSForegroundColorAttributeName : UIColor.white,
    NSFontAttributeName : UIFont.systemFont(ofSize: 17)
]
UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).setTitleTextAttributes(attributes, for: .normal)
11
votes

Swift 5

let attributes:[NSAttributedString.Key: Any] = [
    .foregroundColor: UIColor.black,
    .font: UIFont.systemFont(ofSize: 17)
]
UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).setTitleTextAttributes(attributes, for: .normal)
7
votes

If you just want to modify Cancel button, you can do it by:

if let cancelButton = searchBar.valueForKey("cancelButton") as? UIButton {
    cancelButton.setTitle(<your_string>, forState: <UIControlState>)
    cancelButton.setTitleColor(<your_uicolor>, forState: <UIControlState>)
    cancelButton.setAttributedTitle(<your_nsattributedstring>, forState: <UIControlState>)
}

where searchBar is your UISearchBar object.

5
votes

Based on htinlinn's answer, this is what I used in my viewDidLoad method of the view controller using the search bar in iOS 7:

[[UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil]
                     setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor whiteColor], NSForegroundColorAttributeName, nil] 
                                   forState:UIControlStateNormal];
1
votes

Simplified Swift version of @htinlinn answer:

let attributes = [
    NSForegroundColorAttributeName : UIColor.textBlueColor,
    NSFontAttributeName : UIFont.systemFontOfSize(13)
]
UIBarButtonItem.appearanceWhenContainedInInstancesOfClasses([UISearchBar.self]).setTitleTextAttributes(attributes, forState: .Normal)
0
votes

For modifying the search bar cancel button you have take Button object and change the reference of that button to your custom button.

UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(50,20,300,30)];
searchBar.delegate = self;
searchBar.barStyle = UIBarStyleDefault;
searchBar.showsCancelButton = YES;
UIButton *cancelButton;
for (id button in searchBar.subviews)
{
    if ([button isKindOfClass:[UIButton class]])
   {
        cancelButton=(UIButton*)button;
        break;
   }
}
0
votes

You can use the tint property of searchBar to change the color of searchBar, cancel button's color will get changed but according to the color of UISearchBar. I can't be edited manually. But you can always put a custom over it in the interface builder which will hide the native cancel button. And the user will use your custom button as the cancel button of the searchBar.

0
votes

Swift solution after iOS 9.0 (by modifying htinlinn's answer):

if #available(iOS 9.0, *) {
    UIBarButtonItem.appearanceWhenContainedInInstancesOfClasses([UISearchBar.classForCoder()])
        .setTitleTextAttributes([
            NSFontAttributeName: UIFont.systemFontOfSize(12),
            NSForegroundColorAttributeName: UIColor.blueColor(),
            NSShadowAttributeName: NSShadow(color: UIColor.redColor(), offset: CGSizeMake(0, -1), blurRadius: 2)
            ],
            forState: UIControlState.Normal)
} else {
    // Link to Objective-C Method
}

And the current Objective-C method (UITextAttributeTextColor is deprecated since iOS 7.0):

[[UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil]
 setTitleTextAttributes:@{
                          NSForegroundColorAttributeName: [UIColor blueColor],
                          NSFontAttributeName: [UIFont systemFontOfSize:12]}
 forState:UIControlStateNormal];

My little shadow extension used in the code above:

extension NSShadow {
    convenience init(color: AnyObject!, offset: CGSize, blurRadius: CGFloat) {
        self.init()
        self.shadowColor = color
        self.shadowOffset = offset
        self.shadowBlurRadius = blurRadius
    }
}
-1
votes

Try this one:

[[UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil] setTitleTextAttributes:@{NSFontAttributeName:[UIFont fontWithName:@"SourceSansPro-Regular" size:14]} forState:UIControlStateNormal];
-1
votes

A much better solution here

UIButton *cancelButton = [searchBar valueForKey:@"_cancelButton"];
[cancelButton setTitleColor:[UIColor yourColor] forState:UIControlStateNormal];
[cancelButton setTitle:@"Your Text" forState:UIControlStateNormal];

and similarly you can change other style and text properties of the button.

For iOS 13.* (@AnujAroshA answer in comments)

UIButton *cancelButton = [searchBar valueForKey:@"cancelButton"];