Changing UISearchBar search field background - ios

I have a UISearchBar contained within a UIView and the UIView has been assigned to a UITableView's tableHeaderView. I'm trying to style the UISearchBar to look like this:
Out of the gate, this is what it looks like:
There are loads of SO questions and answers on how to style UISearchBar, its search field, etc., some with particular attention to backgrounds. Many of them involve traversing the UISearchBar's subviews, finding a UISearchBarBackground (or _UISearchBarSearchFieldBackgroundView) object, and setting its background color directly. I'm trying to find a supported API for doing this, however...
The setSearchFieldBackgroundImage:forState: method seems to have great potential, but this is what I get when I use a 1px white (or transparent) image using UIControlStateNormal:
Any ideas as to how to get this to work? I'd appreciate someone pointing me to a SO post that answers this, but I really do think I've read them all. Thanks a ton.

you can use the appearanceWhenContainedIn to target elements without traversing the view hierarchy. Something like:
[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setBackgroundColor:[UIColor whiteColor]];
[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setTextColor:[UIColor lightGrayColor]];
UPDATE:
As appearanceWhenContainedIn is now deprecated, use
[[UITextField appearanceWhenContainedInInstancesOfClasses:#[[UISearchBar self]]] <your setter here>];

I think the problem here is that when you use setSearchFieldBackgroundImage:forState:, the height of your image actually determines the height of the search field. The standard search field (at least as of iOS 8) is 28 points tall, so an image that height should give the effect you're after.
(Somewhat confusingly, this also means that a nine-part stretchable image generally won't look right—so if you were going for a look that wasn't just white on white, you need to use a three-part stretchable image that only stretches horizontally.)

Above iOS 5.0
[[UISearchBar appearance] setSearchFieldBackgroundImage:[UIImage imageNamed:#"YourBackground.png"]forState:UIControlStateNormal];

Please try following code
[[UISearchBar appearance]setBackgroundImage:[UIImage imageNamed:#“searchbar_bg.png"]];
for (UIView *searchbuttons in searchBar.subviews) {
if ([searchbuttons isKindOfClass:[UIButton class]]) {
UIButton *cancelbutton = (UIButton *)searchbuttons;
[cancelbutton setBackgroundImage:[UIImage imageNamed:#“canelBtn.png"] forState:UIControlStateNormal];
}
}
UITextField *searchField = [searchBar valueForKey:#"_searchField"];
searchField.background = [UIImage imageNamed:#"bg.png"];

You can use either the barTintColor or the backgroundImage property of the UISearchBar to directly accomplish what you are trying to do.
I reproduced your problem, and it seems to be solved by:
self.searchDisplayController.searchBar.barTintColor = [UIColor whiteColor];
or
self.searchDisplayController.searchBar.backgroundImage = [self imageWithColor:[UIColor whiteColor]];
P.S. If you are using the backgroundImage solution, you'll need to make the method imageWithColor as follows
- (UIImage *)imageWithColor:(UIColor *)color {
CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
Tell me if it works!

iO9 Perfect works.
- (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;
}

#joneswah's answer is depricated in iOS 9.
For iOS 9 put this in your AppDelegate.m. I also added workaround for keyboard opening lag, when keyboard is initiated for the first time.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Remove lag on oppening the keyboard for the first time when clicked on any UITextField
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]];//background color
[[UITextField appearanceWhenContainedInInstancesOfClasses:#[[UISearchBar class]]] setTextColor:[UIColor blackColor];//text color
return YES;
}

As others suggested, you need to traverse through your searchbar's subviews and finding the UITextField instance. BUT, you need to set its layer.backgroundColor, as setting the backgroundColor property has no effect. I'll give an example:
for view in searchBar.subviews {
for subview in view.subviews {
if let searchField = subview as? UITextField {
searchField.layer.backgroundColor = UIColor.whiteColor().CGColor
}
}
}
This will give you what you need.

My answer stably works on ios 5 and above, including this 10. Without hacks and KVO, by Apple Way

The following code will achieve the result.
_sbAddress.barTintColor = [UIColor whiteColor];
for (UIView *subView in _sbAddress.subviews) {
for(id field in subView.subviews){
if ([field isKindOfClass:[UITextField class]]) {
UITextField *textField = (UITextField *)field;
[textField setPlaceholder:#"Search"];
}
}
}
OR
[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setPlaceholder:#"Search"];

Related

UISearchBar box color

I have a search bar and beside that i want a button with the same background color as the one in search bar. Does anyone know this color?
I think its #A4A4A4
Or you could try the Eyedropper tool in photoshop
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...
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]];
}
}

Customizing UISearch bar

I am trying to customize my search bar like this
So far I have managed to do upto this
Now I need to know how to add image on right side, shaping the corners and changing background to an image. This is my code so far. I can do this with help of UITextField but I want to do this using the UISearchBar. Any help??
- (void)setSearchIconToFavicon
{
// commented are the things I tried out
UITextField *searchField = nil;
for (UIView *subview in searchBar.subviews)
{
if ([subview isKindOfClass:[UITextField class]])
{
searchField = (UITextField *)subview;
break;
}
}
if (searchField)
{
UIImage *image = [UIImage imageNamed: #"search_btn.png"];
UIImageView *iView = [[UIImageView alloc] initWithImage:image];
//UIImage *image2 = [UIImage imageNamed: #"search_next_btn.png"];
//UIImageView *iView2 = [[UIImageView alloc] initWithImage:image2];
searchField.leftView = iView;
//searchField.rightView=iView2;
[[self.searchBar.subviews objectAtIndex:0] removeFromSuperview];
searchField.textColor = [UIColor grayColor];
}
}
You can replace the Bookmark image instead, and adjust its offset if necessary.Like this..
[self.searchDisplayController.searchBar setImage:[UIImage imageNamed:#"yourImage"] forSearchBarIcon:UISearchBarIconBookmark state:UIControlStateNormal];
[self.searchDisplayController.searchBar setPositionAdjustment:UIOffsetMake(0, 0) forSearchBarIcon:UISearchBarIconBookmark];
And you can handle the button event in the delegate method:
- (void)searchBarBookmarkButtonClicked:(UISearchBar *)searchBar
i Hope you got my point.
You can this line of code if your target application is >=5.0 to change background image of search bar.
[[UISearchBar appearance] setSearchFieldBackgroundImage:[UIImage imageNamed:#"searchbar.png"]forState:UIControlStateNormal];

customizing UISearchBarIconClear for UIControlStateHighlighted does not work

I have a UISearchBar for which I have set a custom UISearchBarIconClear for UiControlStateNormal.
[mySearchBar setImage:myImage forSearchBarIcon:UISearchBarIconClear state:UIControlStateNormal];
This part works as it should but unfortunately when tapping the clear button, it changes from the image I set, to the original default gray one.
I have tried setting the image for UIControlStateHighlighted, but apparently that does not work.
The documentation actually states
Valid states are UIControlStateNormal and UIControlStateDisabled.
What's the point of setting a custom button for the default state if you can't set it for the highlighted state? Am I missing something? Any thoughts or workarounds appreciated, thanks!
I had the same problem, and adjusting the order of the statements solved it:
So instead of doing UIControlStateNormal first then UIControlStateHighlighted, set the image for Highlighted state first
[searchBar setImage:clearIcon forSearchBarIcon:UISearchBarIconClear state:UIControlStateHighlighted];
[searchBar setImage:clearIcon forSearchBarIcon:UISearchBarIconClear state:UIControlStateNormal];
How about using appearance proxy?
[[UIButton appearanceWhenContainedIn:[UITextField class], [UISearchBar class], nil] setImage:myImage forState:UIControlStateHighlighted];
I just had the same problem as you described with the clear icon reseting to the default icon upon being pressed.
This seems to be due to me trying to use the same UIImage for both the normal and highlighted state, switching to a different image for the highlighted state fixed the problem.
Came across the same issue a little bit earlier today, here is my really ugly workaround that I probably wouldn't use myself.
for(UIView *subView in searchBar.subviews) {
if([subView isKindOfClass: [UITextField class]]){
UITextField *searchField = (UITextField *)subView;
CGFloat myWidth = 26.0f;
CGFloat myHeight = 30.0f;
UIButton *myButton = [[UIButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, myWidth, myHeight)];
[myButton setImage:[UIImage imageNamed:#"searchbariconclear"] forState:UIControlStateNormal];
[myButton setImage:[UIImage imageNamed:#"searchbariconclear"] forState:UIControlStateHighlighted];
[myButton addTarget:self action:#selector(clearsearchbar) forControlEvents:UIControlEventTouchUpInside];
searchField.rightView = myButton;
searchField.rightViewMode = UITextFieldViewModeAlways;
searchField.clearButtonMode = UITextFieldViewModeNever;
}
}
And then..
- (void)clearsearchbar {
for(UIView *subView in searchBar.subviews) {
if([subView isKindOfClass: [UITextField class]]){
UITextField *searchField = (UITextField *)subView;
searchField.text = nil;
}
}
}
Three problems with this approach..
Since we're digging around inside the subviews of the searchbar it could break some day with an OS update.
This doesn't behave exactly like UISearchBarIconClear, in that the clear icon will always be visible.. You could potentially try testing with other UITextFieldViewModes using this approach, I didn't mainly because, from what I know none of the others would be ideal here, for some reason or the other.
Maybe it's just me, but I don't really think that something that introduces two problems when trying to solve one, is a solution. :-)
If anyone has a better way of tackling this problem, I'd love to hear it too.

Change text color of search bar ios

Is it possible to change the text color of the search bar? I don't seem to have access to the UISearchBarTextField class...
firstly, you find the subview in UISearchBar, then find the UITextField in sub View then change color
Try this code:-
for(UIView *subView in searchBar.subviews){
if([subView isKindOfClass:UITextField.class]){
[(UITextField*)subView setTextColor:[UIColor blueColor]];
}
}
for Ios 5 +
[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setTextColor:[UIColor blueColor]];
As of iOS 5, the right way to do this is using the appearance protocol.
For example:
[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setTextColor:[UIColor blueColor]];
You can set the attributes like so, call this in your controller.
[[UITextField appearanceWhenContainedIn:[self class], nil] setDefaultTextAttributes:#{NSForegroundColorAttributeName:[UIColor whiteColor], NSFontAttributeName:[UIFont systemFontOfSize:14]}];
*note that this will change all UITextFields in your controller
The original UISearchBar hierarchy has changed since the original post and the UITextField is no longer a direct subview. The below code makes no assumptions about the UISearchBar hierarchy.
This is also useful when you don't want to change the search bar's text color throughout the entire application (i.e. using appearanceWhenContainedIn).
/**
* A recursive method which sets all UITextField text color within a view.
* Makes no assumptions about the original view's hierarchy.
*/
+(void) setAllTextFieldsWithin:(UIView*)view toColor:(UIColor*)color
{
for(UIView *subView in view.subviews)
{
if([subView isKindOfClass:UITextField.class])
{
[(UITextField*)subView setTextColor:color];
}
else
{
[self setAllTextFieldsWithin:subView toColor:color];
}
}
}
Usage:
[MyClass setAllTextFieldsWithin:self.mySearchBar toColor:[UIColor blueColor]];

Changing Tint / Background color of UITabBar

The UINavigationBar and UISearchBar both have a tintColor property that allows you to change the tint color (surprising, I know) of both of those items. I want to do the same thing to the UITabBar in my application, but have found now way to change it from the default black color. Any ideas?
iOS 5 has added some new appearance methods for customising the look of most UI elements.
You can target every instance of a UITabBar in your app by using the appearance proxy.
For iOS 5 + 6:
[[UITabBar appearance] setTintColor:[UIColor redColor]];
For iOS 7 and above, please use the following:
[[UITabBar appearance] setBarTintColor:[UIColor redColor]];
Using the appearance proxy will change any tab bar instance throughout the app. For a specific instance, use one of the new properties on that class:
UIColor *tintColor; // iOS 5+6
UIColor *barTintColor; // iOS 7+
UIColor *selectedImageTintColor;
UIImage *backgroundImage;
UIImage *selectionIndicatorImage;
I have been able to make it work by subclassing a UITabBarController and using private classes:
#interface UITabBarController (private)
- (UITabBar *)tabBar;
#end
#implementation CustomUITabBarController
- (void)viewDidLoad {
[super viewDidLoad];
CGRect frame = CGRectMake(0.0, 0.0, self.view.bounds.size.width, 48);
UIView *v = [[UIView alloc] initWithFrame:frame];
[v setBackgroundColor:kMainColor];
[v setAlpha:0.5];
[[self tabBar] addSubview:v];
[v release];
}
#end
I have an addendum to the final answer. While the essential scheme is correct, the trick of using a partially transparent color can be improved upon. I assume that it's only for letting the default gradient to show through. Oh, also, the height of the TabBar is 49 pixels rather than 48, at least in OS 3.
So, if you have a appropriate 1 x 49 image with a gradient, this is the version of viewDidLoad you should use:
- (void)viewDidLoad {
[super viewDidLoad];
CGRect frame = CGRectMake(0, 0, 480, 49);
UIView *v = [[UIView alloc] initWithFrame:frame];
UIImage *i = [UIImage imageNamed:#"GO-21-TabBarColorx49.png"];
UIColor *c = [[UIColor alloc] initWithPatternImage:i];
v.backgroundColor = c;
[c release];
[[self tabBar] addSubview:v];
[v release];
}
When you just use addSubview your buttons will lose clickability, so instead of
[[self tabBar] addSubview:v];
use:
[[self tabBar] insertSubview:v atIndex:0];
There is no simple way to do this, you basically need to subclass UITabBar and implement custom drawing to do what you want. It is quite a bit of work for the effect, but it may be worth it. I recommend filing a bug with Apple to get it added to a future iPhone SDK.
Following is the perfect solution for this. This works fine with me for iOS5 and iOS4.
//---- For providing background image to tabbar
UITabBar *tabBar = [tabBarController tabBar];
if ([tabBar respondsToSelector:#selector(setBackgroundImage:)]) {
// ios 5 code here
[tabBar setBackgroundImage:[UIImage imageNamed:#"image.png"]];
}
else {
// ios 4 code here
CGRect frame = CGRectMake(0, 0, 480, 49);
UIView *tabbg_view = [[UIView alloc] initWithFrame:frame];
UIImage *tabbag_image = [UIImage imageNamed:#"image.png"];
UIColor *tabbg_color = [[UIColor alloc] initWithPatternImage:tabbag_image];
tabbg_view.backgroundColor = tabbg_color;
[tabBar insertSubview:tabbg_view atIndex:0];
}
On iOS 7:
[[UITabBar appearance] setBarTintColor:[UIColor colorWithRed:(38.0/255.0) green:(38.0/255.0) blue:(38.0/255.0) alpha:1.0]];
I also recommend setting first depending on your visual desires:
[[UITabBar appearance] setBarStyle:UIBarStyleBlack];
The bar style puts a subtle separator between your view content and your tab bar.
[[self tabBar] insertSubview:v atIndex:0];
works perfectly for me.
for me its very simple to change the color of Tabbar like :-
[self.TabBarController.tabBar setTintColor:[UIColor colorWithRed:0.1294 green:0.5686 blue:0.8353 alpha:1.0]];
[self.TabBarController.tabBar setTintColor:[UIColor "YOUR COLOR"];
Try this!!!
[[UITabBar appearance] setTintColor:[UIColor redColor]];
[[UITabBar appearance] setBarTintColor:[UIColor yellowColor]];
for just background color
Tabbarcontroller.tabBar.barTintColor=[UIColor redcolour];
or this in App Delegate
[[UITabBar appearance] setBackgroundColor:[UIColor blackColor]];
for changing color of unselect icons of tabbar
For iOS 10:
// this code need to be placed on home page of tabbar
for(UITabBarItem *item in self.tabBarController.tabBar.items) {
item.image = [item.image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
}
Above iOS 10:
// this need to be in appdelegate didFinishLaunchingWithOptions
[[UITabBar appearance] setUnselectedItemTintColor:[UIColor blackColor]];
There are some good ideas in the existing answers, many work slightly differently and what you choose will also depend on which devices you target and what kind of look you're aiming to achieve. UITabBar is notoriously unintuitive when it come to customizing its appearance, but here are a few more tricks that may help:
1). If you're looking to get rid of the glossy overlay for a more flat look do:
tabBar.backgroundColor = [UIColor darkGrayColor]; // this will be your background
[tabBar.subviews[0] removeFromSuperview]; // this gets rid of gloss
2). To set custom images to the tabBar buttons do something like:
for (UITabBarItem *item in tabBar.items){
[item setFinishedSelectedImage:selected withFinishedUnselectedImage:unselected];
[item setImageInsets:UIEdgeInsetsMake(6, 0, -6, 0)];
}
Where selected and unselected are UIImage objects of your choice. If you'd like them to be a flat colour, the simplest solution I found is to create a UIView with the desired backgroundColor and then just render it into a UIImage with the help of QuartzCore. I use the following method in a category on UIView to get a UIImage with the view's contents:
- (UIImage *)getImage {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [[UIScreen mainScreen]scale]);
[[self layer] renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return viewImage;
}
3) Finally, you may want to customize the styling of the buttons' titles. Do:
for (UITabBarItem *item in tabBar.items){
[item setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys:
[UIColor redColor], UITextAttributeTextColor,
[UIColor whiteColor], UITextAttributeTextShadowColor,
[NSValue valueWithUIOffset:UIOffsetMake(0, 1)], UITextAttributeTextShadowOffset,
[UIFont boldSystemFontOfSize:18], UITextAttributeFont,
nil] forState:UIControlStateNormal];
}
This lets you do some adjustments, but still quite limited. Particularly, you cannot freely modify where the text is placed within the button, and cannot have different colours for selected/unselected buttons. If you want to do more specific text layout, just set UITextAttributeTextColor to be clear and add your text into the selected and unselected images from part (2).
[v setBackgroundColor ColorwithRed: Green: Blue: ];
Another solution (which is a hack) is to set the alpha on the tabBarController to 0.01 so that it is virtually invisible yet still clickable. Then set a an ImageView control on the bottom of the MainWindow nib with your custom tabbar image underneath the alpha'ed tabBarCOntroller. Then swap the images, change colors or hightlight when the tabbarcontroller switches views.
However, you lose the '...more' and customize functionality.
Hi There am using iOS SDK 4 and i was able to solve this issue with just two lines of code and it's goes like this
tBar.backgroundColor = [UIColor clearColor];
tBar.backgroundImage = [UIImage imageNamed:#"your-png-image.png"];
Hope this helps!
if ([tabBar respondsToSelector:#selector(setBackgroundImage:)]) {
// ios 5 code here
[tabBar setBackgroundImage:[UIImage imageNamed:#"image.png"]];
}
else {
// ios 4 code here
CGRect frame = CGRectMake(0, 0, 480, 49);
UIView *tabbg_view = [[UIView alloc] initWithFrame:frame];
UIImage *tabbag_image = [UIImage imageNamed:#"image.png"];
UIColor *tabbg_color = [[UIColor alloc] initWithPatternImage:tabbag_image];
tabbg_view.backgroundColor = tabbg_color;
[tabBar insertSubview:tabbg_view atIndex:0];
}
Swift 3.0 answer: (from Vaibhav Gaikwad)
For changing color of unselect icons of tabbar:
if #available(iOS 10.0, *) {
UITabBar.appearance().unselectedItemTintColor = UIColor.white
} else {
// Fallback on earlier versions
for item in self.tabBar.items! {
item.image = item.image?.withRenderingMode(UIImageRenderingMode.alwaysOriginal)
}
}
For changing text color only:
UITabBarItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.white], for: .normal)
UITabBarItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.red, for: .selected)
Swift 3 using appearance from your AppDelegate do the following:
UITabBar.appearance().barTintColor = your_color

Resources