68

I know how to remove/change UISearchBar background color around search field:

[[self.searchBar.subviews objectAtIndex:0] removeFromSuperview];
self.searchBar.backgroundColor = [UIColor grayColor];

achieved UISearchBar customization

But don't know how to do this inside it like that:

desired UISearchBar customization

This needs to be compatible with iOS 4.3+.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Borut Tomazin
  • 8,041
  • 11
  • 78
  • 91
  • try this http://stackoverflow.com/a/5557255/1570343 – Pranjal Bikash Das Dec 11 '12 at 09:38
  • This is not ok. I want to get rid of white color inside component. Take a look at the question... – Borut Tomazin Dec 11 '12 at 09:44
  • @BorutTomazin test my code its work fine and here you can change the searchBar icon with 4 types of icon which i define in answer but you want to use white searchbar so just add image on the searchbaricon with another white searchbar icon and also add image as a background of UITextField of searchbar – Paras Joshi Dec 11 '12 at 10:32
  • 1
    Possible duplicate of [UISearchBar: changing background color of input field](http://stackoverflow.com/questions/7229147/uisearchbar-changing-background-color-of-input-field) – Max MacLeod Nov 18 '15 at 12:25
  • For Swift 3. I found a solution here: [**Customize textfield easily**](http://stackoverflow.com/a/40105165/4593553) – Jerome Oct 18 '16 at 10:05

26 Answers26

47

Just customize the text field itself.

I am simply doing this and it works fine for me (iOS 7).

UITextField *txfSearchField = [_searchBar valueForKey:@"_searchField"];
txfSearchField.backgroundColor = [UIColor redColor];

This way you don't need to create an image, size it, etc...

AbuZubair
  • 1,236
  • 14
  • 20
42

Details

  • Xcode Version 11.0 (11A420a), swift 5

UISearchBar customising sample

Solution

import UIKit

extension UISearchBar {
    func getTextField() -> UITextField? { return value(forKey: "searchField") as? UITextField }
    func setTextField(color: UIColor) {
        guard let textField = getTextField() else { return }
        switch searchBarStyle {
        case .minimal:
            textField.layer.backgroundColor = color.cgColor
            textField.layer.cornerRadius = 6
        case .prominent, .default: textField.backgroundColor = color
        @unknown default: break
        }
    }
}

Usage

let searchBar = UISearchBar(frame: CGRect(x: 0, y: 20, width: UIScreen.main.bounds.width, height: 44))
//searchBar.searchBarStyle = .prominent
view.addSubview(searchBar)
searchBar.placeholder = "placeholder"
searchBar.setTextField(color: UIColor.green.withAlphaComponent(0.3))

Result 1

 searchBar.searchBarStyle = .prominent // or default

enter image description here

Result 2

 searchBar.searchBarStyle = .minimal

enter image description here

Full sample

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let searchBar = UISearchBar(frame: CGRect(x: 0, y: 20, width: UIScreen.main.bounds.width, height: 44))
        //searchBar.searchBarStyle = .minimal
        searchBar.searchBarStyle = .prominent
        view.addSubview(searchBar)
        searchBar.placeholder = "placeholder"
        searchBar.setTextField(color: UIColor.green.withAlphaComponent(0.3))
    }
}
Vasily Bodnarchuk
  • 24,482
  • 9
  • 132
  • 127
  • 2
    This was killing me...thanks for pointing out that for minimal you had to do layer.backgroundColor... – tanya Feb 02 '17 at 19:23
  • 2
    One interesting problem with this solution is that when type is .minimal and one sets the background to white -> the background becomes grey. this is due to the fact that the top of the view is taken by an image named _UISearchBarSearchFieldBackgroundView – EmilDo Mar 13 '17 at 09:12
  • Can't understand. Can you show the code? I have no problem with setting searchBar.backgroundColor = .white. – Vasily Bodnarchuk Mar 13 '17 at 09:21
  • 1
    Beautiful solution! Thank you. – Tim Friedland Jul 26 '17 at 13:04
  • 1
    **For guys looking for a better solution, I recommend you read `EvGeniy Ilyin`'s, which is way bellow the many ugly solutions.** (cmd+F, search this page.) `UISearchBar.appearance().setSearchFieldBackgroundImage(whiteImage, for: .normal)` – wzso Sep 16 '17 at 11:41
  • iOS 11 for minimal searcher, setting .layer background doesn't work anymore. It seems there is an additional view on top of the textfield. – coolcool1994 Oct 01 '17 at 05:43
  • why we use layer for minimal searchBarStyle .? because when I remove backgroundColor without layer it not set the color that's why . – Yogesh Patel Jan 29 '19 at 06:25
  • @ApoorvKhatreja it is possible. I will wait for the official Xcode release and then update the code. – Vasily Bodnarchuk Aug 27 '19 at 21:35
39

Solution which doesn't involve any private API ! :)

Currently (probably since iOS 5 ) you can do this, for simply one colour cases, in this way:

[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setBackgroundColor:[UIColor redColor]];

but please keep in mind that as it basis on appearance the change will be global for the app (it can be an advantage or a disadvantage of the solution).

For Swift you can use (it will work for iOS 9 and above):

if #available(iOS 9.0, *) {
    UITextField.appearanceWhenContainedInInstancesOfClasses([UISearchBar.self]).backgroundColor = UIColor.darkGrayColor()
}

You do not need #available if your project supports iOS 9 and newer.

If you need to support earlier versions of iOS and want to use Swift take a look at this question.

Community
  • 1
  • 1
Julian
  • 9,299
  • 5
  • 48
  • 65
36

Use this code to change the searchBar's UITextField backgroundImage:

UITextField *searchField;
NSUInteger numViews = [searchBar.subviews count];
for (int i = 0; i < numViews; i++) {
    if ([[searchBar.subviews objectAtIndex:i] isKindOfClass:[UITextField class]]) { //conform?
        searchField = [searchBar.subviews objectAtIndex:i];
    }
}
if (searchField) {
    searchField.textColor = [UIColor whiteColor];
    [searchField setBackground: [UIImage imageNamed:@"yourImage"]]; //set your gray background image here
    [searchField setBorderStyle:UITextBorderStyleNone];
}

Use the below code to change the UISearchBarIcon:

 UIImageView *searchIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"yourSearchBarIconImage"]];
searchIcon.frame = CGRectMake(10, 10, 24, 24);
[searchBar addSubview:searchIcon];
[searchIcon release];

Also, to change the searchBar icon you can use the following built-in method on UISearchBar (which is available from iOS 5+):

- (void)setImage:(UIImage *)iconImage forSearchBarIcon:(UISearchBarIcon)icon state:(UIControlState)state

Here you can set 4 types of UISearchBarIcon i.e.:

  1. UISearchBarIconBookmark
  2. UISearchBarIconClear
  3. UISearchBarIconResultsList
  4. UISearchBarIconSearch

I hope this help you...

Brian Flanagan
  • 4,612
  • 5
  • 29
  • 38
Paras Joshi
  • 20,427
  • 11
  • 57
  • 70
  • @BorutTomazin i just add the code for change the textfield backgroundcolor of searchbar and when i get output for search icon i'll also post code hope it help you... – Paras Joshi Dec 11 '12 at 10:11
  • This way is not a good way to do it. It can easily break your app in coming iOS updates. *EDIT* Sorry, just saw that the OP needed it to be compatible with iOS 4. – Accatyyc Dec 11 '12 at 10:34
  • @Accatyyc this is give perfact output which he wants and its problem occure in bellow the version of 5.0 or 4.3 so its fine and if you have a solution then post the code dude i have this solution which may useful ... – Paras Joshi Dec 11 '12 at 10:43
  • not the best solution. see *EvGeniy Ilyin*'s, which is way bellow the many ugly solutions. (cmd+F, search this page.) `UISearchBar.appearance().setSearchFieldBackgroundImage(white‌​Image, for: .normal)` – wzso Sep 16 '17 at 11:45
24

According to the UISearchBar documentation:

You should use this function for iOS 5.0+.

- (void)setSearchFieldBackgroundImage:(UIImage *)backgroundImage forState:(UIControlState)state

Usage example:

[mySearchBar setSearchFieldBackgroundImage:myImage forState:UIControlStateNormal];

Sadly, in iOS 4 you need to revert to less sophisticated methods. See other answers.

Accatyyc
  • 5,798
  • 4
  • 36
  • 51
20

As Accatyyc says for iOS5+ use setSearchFieldBackgroundImage, but you either need to create a graphic, or do the following:

CGSize size = CGSizeMake(30, 30);
// create context with transparent background
UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale);

// Add a clip before drawing anything, in the shape of an rounded rect
[[UIBezierPath bezierPathWithRoundedRect:CGRectMake(0,0,30,30)
                            cornerRadius:5.0] addClip];
[[UIColor grayColor] setFill];

UIRectFill(CGRectMake(0, 0, size.width, size.height));
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

[self.searchBar setSearchFieldBackgroundImage:image forState:UIControlStateNormal];
To1ne
  • 1,108
  • 2
  • 12
  • 22
Nick Hingston
  • 8,724
  • 3
  • 50
  • 59
17

what about apple way?

UISearchBar.appearance().setSearchFieldBackgroundImage(myImage, for: .normal)

you can set any image on your design!

But if you want create all programmaticle, you ca do this


my solution on Swift 3

let searchFieldBackgroundImage = UIImage(color: .searchBarBackground, size: CGSize(width: 44, height: 30))?.withRoundCorners(4)
UISearchBar.appearance().setSearchFieldBackgroundImage(searchFieldBackgroundImage, for: .normal)

where i use helpers extension

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)
    }

    public func withRoundCorners(_ cornerRadius: CGFloat) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        let rect = CGRect(origin: CGPoint.zero, size: size)
        let context = UIGraphicsGetCurrentContext()
        let path = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius)

        context?.beginPath()
        context?.addPath(path.cgPath)
        context?.closePath()
        context?.clip()

        draw(at: CGPoint.zero)

        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext();

        return image;
    }

}
EvGeniy Ilyin
  • 1,817
  • 1
  • 21
  • 38
  • This is surely the best and the most graceful way. Thanks! Saved my life. – wzso Sep 16 '17 at 11:37
  • 1
    This is the correct way. I was just about to post a version of this. Good work! Very Complete! – Jbryson May 03 '18 at 18:03
  • 3
    Maybe I am doing something wrong, but this sets the background image of the entire search bar and not the just the background image inside the text field – btomtom5 Jan 31 '19 at 02:47
  • 1
    Finally a solution that doesn't use the private API! I went with UISearchBar.appearance().setSearchFieldBackgroundImage(UIImage(), for: .normal) to completely remove the grey image – Merricat Nov 21 '19 at 19:06
14

To do this on iOS 13+,

searchController.searchBar.searchTextField.backgroundColor = // your color here

Do note that by default the searchTextField.borderStyle is set to roundedRect, which applies a slight gray overlay on top of the color that you will set. If this is undesired, do

searchController.searchBar.searchTextField.borderStyle = .none

This will get rid of the gray overlay, but also get rid of the rounded corners.

Apoorv Khatreja
  • 435
  • 4
  • 9
7

I've found this to be the best way to customize the appearance of various search bar attributes in Swift 2.2 and iOS 8+ using UISearchBarStyle.Minimal

searchBar = UISearchBar(frame: CGRectZero)
searchBar.tintColor = UIColor.whiteColor() // color of bar button items
searchBar.barTintColor = UIColor.fadedBlueColor() // color of text field background
searchBar.backgroundColor = UIColor.clearColor() // color of box surrounding text field
searchBar.searchBarStyle = UISearchBarStyle.Minimal

// Edit search field properties
if let searchField = searchBar.valueForKey("_searchField") as? UITextField  {
  if searchField.respondsToSelector(Selector("setAttributedPlaceholder:")) {
    let placeholder = "Search"
    let attributedString = NSMutableAttributedString(string: placeholder)
    let range = NSRange(location: 0, length: placeholder.characters.count)
    let color = UIColor(white: 1.0, alpha: 0.7)
    attributedString.addAttribute(NSForegroundColorAttributeName, value: color, range: range)
    attributedString.addAttribute(NSFontAttributeName, value: UIFont(name: "AvenirNext-Medium", size: 15)!, range: range)
    searchField.attributedPlaceholder = attributedString

    searchField.clearButtonMode = UITextFieldViewMode.WhileEditing
    searchField.textColor = .whiteColor()
  }
}

// Set Search Icon
let searchIcon = UIImage(named: "search-bar-icon")
searchBar.setImage(searchIcon, forSearchBarIcon: .Search, state: .Normal)

// Set Clear Icon
let clearIcon = UIImage(named: "clear-icon")
searchBar.setImage(clearIcon, forSearchBarIcon: .Clear, state: .Normal)

// Add to nav bar
searchBar.sizeToFit()
navigationItem.titleView = searchBar

enter image description here

Alex Koshy
  • 1,613
  • 15
  • 17
6

without using private API's:

for (UIView* subview in [[self.searchBar.subviews lastObject] subviews]) {
    if ([subview isKindOfClass:[UITextField class]]) {
        UITextField *textField = (UITextField*)subview;
        [textField setBackgroundColor:[UIColor redColor]];
    }
}
Tomer Even
  • 4,820
  • 2
  • 30
  • 36
  • It doesn't use private API but it still relies on private implementation details (i.e. the internal view hierarchy of the search bar). This implementation could change at any time. – Greg Brown Nov 29 '17 at 12:18
6

try this in iOS13 in swift

@IBOutlet weak var searchBar: UISearchBar!
searchBar.barTintColor = .systemIndigo
searchBar.searchTextField.backgroundColor = .white
Sanjeet Chand
  • 181
  • 6
  • 6
5

For Changing Only Color :

searchBar.tintColor = [UIColor redColor];

For Applying Background Image :

[self.searchBar setSearchFieldBackgroundImage:
                          [UIImage imageNamed:@"Searchbox.png"]
                                     forState:UIControlStateNormal];
Marius Waldal
  • 9,537
  • 4
  • 30
  • 44
Pushkraj Lanjekar
  • 2,254
  • 1
  • 21
  • 34
5

A better solution is to set the appearance of the UITextField inside UISearchBar

[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setBackgroundColor:[UIColor grayColor]];
Mahmoud Adam
  • 5,772
  • 5
  • 41
  • 62
4

Just traverse all views using a category method (verified in iOS 7 and doesn't use private API):

@implementation UISearchBar (MyAdditions)

- (void)changeDefaultBackgroundColor:(UIColor *)color {
  for (UIView *subview in self.subviews) {
    for (UIView *subSubview in subview.subviews) {
      if ([subSubview isKindOfClass:[UITextField class]]) {
        UITextField *searchField = (UITextField *)subSubview;
        searchField.backgroundColor = color;
        break;
      }
    }
  }
}

@end

So after importing the category into your class, just use it like:

[self.searchBar changeDefaultBackgroundColor:[UIColor grayColor]];

Keep in mind, if you put this immediately after the [[UISearchBar alloc] init] line, it won't work yet since the subviews of the search bar are still being created. Put it a few lines down after you setup the rest of the search bar.

iwasrobbed
  • 46,496
  • 21
  • 150
  • 195
3
- (void)viewDidLoad
{
    [super viewDidLoad];
    [[self searchSubviewsForTextFieldIn:self.searchBar] setBackgroundColor:[UIColor redColor]];
}

- (UITextField*)searchSubviewsForTextFieldIn:(UIView*)view
{
    if ([view isKindOfClass:[UITextField class]]) {
        return (UITextField*)view;
    }
    UITextField *searchedTextField;
    for (UIView *subview in view.subviews) {
        searchedTextField = [self searchSubviewsForTextFieldIn:subview];
        if (searchedTextField) {
            break;
        }
    }
    return searchedTextField;
}
Meerschwein Bob
  • 212
  • 2
  • 6
3

This is the Swift version ( swift 2.1 /IOS 9 )

for view in searchBar.subviews {
    for subview in view.subviews {
        if subview .isKindOfClass(UITextField) {
            let textField: UITextField = subview as! UITextField
            textField.backgroundColor = UIColor.lightGrayColor()
        }
    }
}
skypjack
  • 49,335
  • 19
  • 95
  • 187
Mudith Chathuranga Silva
  • 7,253
  • 2
  • 50
  • 58
  • 1
    This had no effect for me. But setting the **textField.layer.backgroundColor** does change the background color. – Ivan Aug 09 '16 at 14:02
3

Searchbar now has a new instance property SearchTextField starting iOS 13, https://developer.apple.com/documentation/uikit/uisearchbar/3175433-searchtextfield

if(@available(iOS 13, *))
    searchBar.searchTextField.backgroundColor = [UIColor whiteColor];
    searchBar.searchTextField.textColor = [UIColor blackColor];
else{
    //API that supports below iOS 13
    //This will set it for all the UISearchBars in your application
    [[UITextField appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setBackgroundColor:[UIColor whiteColor]];
    [[UITextField appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTextColor:[UIColor blackColor]];
}
Manoj Kumar
  • 318
  • 4
  • 14
2

iOS 13, Swift 5

searchBar.searchTextField.backgroundColor = .gray
 searchBar.searchTextField.tintColor = .white
 searchBar.searchTextField.textColor = .white
Azim Shaikh
  • 589
  • 6
  • 18
1

For iOS 9 use this:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.

// Remove lag on oppening the keyboard for the first time
UITextField *lagFreeField = [[UITextField alloc] init];
[self.window addSubview:lagFreeField];
[lagFreeField becomeFirstResponder];
[lagFreeField resignFirstResponder];
[lagFreeField removeFromSuperview];

//searchBar background color change
[[UITextField appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setBackgroundColor:[UIColor greenColor]];
[[UITextField appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTextColor:[UIColor blackColor];

return YES;
}
Undo
  • 25,519
  • 37
  • 106
  • 129
Boris Nikolic
  • 746
  • 14
  • 24
1

Swift 3

for subview in searchBar.subviews {
    for innerSubview in subview.subviews {
        if innerSubview is UITextField {
            innerSubview.backgroundColor = UIColor.YOUR_COLOR_HERE
        }
    }
}
Chris Chute
  • 3,229
  • 27
  • 18
1

For Swift 3+, use this:

for subView in searchController.searchBar.subviews {

    for subViewOne in subView.subviews {

        if let textField = subViewOne as? UITextField {

           subViewOne.backgroundColor = UIColor.red

           //use the code below if you want to change the color of placeholder
           let textFieldInsideUISearchBarLabel = textField.value(forKey: "placeholderLabel") as? UILabel
                textFieldInsideUISearchBarLabel?.textColor = UIColor.blue
        }
     }
}
Alien
  • 576
  • 1
  • 4
  • 16
1

With Swift 4, I would recommend that you only do this, no additional code needed:

self.searchBar.searchBarStyle = .prominent
self.searchBar.barStyle = .black

You can also change .prominent to .minimal should you not want the outer background to be grey.

Chris Herbst
  • 1,241
  • 1
  • 16
  • 28
1

Use it to update search textfield backgroud_color for xcode10 and xcode11 working fine for me

[[UITextField appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTextColor:[UIColor greenColor]];
Szabolcs Páll
  • 1,402
  • 6
  • 25
  • 31
Bh.Singh
  • 41
  • 4
0

@EvGeniy Ilyin EvGeniy Ilyin's solution is the best. I wrote an Objective-C version based on this solution.

Create a UIImage category, and advertise two class methods in UIImage+YourCategory.h

+ (UIImage *)imageWithColor:(UIColor *)color withSize:(CGRect)imageRect;
+ (UIImage *)roundImage:(UIImage *)image withRadius:(CGFloat)radius;

Implement methods in UIImage+YourCategory.m

// create image with your color
+ (UIImage *)imageWithColor:(UIColor *)color withSize:(CGRect)imageRect
{
    UIGraphicsBeginImageContext(imageRect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetFillColorWithColor(context, [color CGColor]);
    CGContextFillRect(context, imageRect);

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return image;
}

// get a rounded-corner image from UIImage instance with your radius
+ (UIImage *)roundImage:(UIImage *)image withRadius:(CGFloat)radius
{
    CGRect rect = CGRectMake(0.0, 0.0, 0.0, 0.0);
    rect.size = image.size;
    UIGraphicsBeginImageContextWithOptions(image.size, NO, [UIScreen mainScreen].scale);
    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect
                                                cornerRadius:radius];
    [path addClip];
    [image drawInRect:rect];

    image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return image;
}

Make your own UISearchBar in your ViewController

CGRect rect = CGRectMake(0.0, 0.0, 44.0, 30.0);
UIImage *colorImage = [UIImage imageWithColor:[UIColor yourColor] withSize:rect];
UIImage *finalImage = [UIImage roundImage:colorImage withRadius:4.0];
[yourSearchBar setSearchFieldBackgroundImage:finalImage forState:UIControlStateNormal];
steveluoxin
  • 419
  • 4
  • 14
0

This Worked for me.

- (void)setupSearchBar
{
    [self.searchBar setReturnKeyType:UIReturnKeySearch];
    [self.searchBar setEnablesReturnKeyAutomatically:NO];
    [self.searchBar setPlaceholder:FOLocalizedString(@"search", nil)];
    [self.searchBar setBackgroundImage:[UIImage new]];
    [self.searchBar setBackgroundColor:[UIColor myGreyBGColor]];
    [self.searchBar setBarTintColor:[UIColor myGreyBGColor]];
    [self.searchBar setTintColor:[UIColor blueColor]];
}
Varun Naharia
  • 5,318
  • 10
  • 50
  • 84
-1

This helped me to change the background color of textField in searchbar.

UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).backgroundColor = .white
Ranu Dhurandhar
  • 93
  • 1
  • 10