Thursday, October 14, 2010

How to Control UISearchBar Background Color

When you have a list, you want to search it. How would you do that? No, don't code it by yourself. Done it, removed it.

By default each UITableView comes with search support via a built-in UISearchDisplayController. You just add and connect UISearchBar to your table in Interface Builder and provide some delegate methods to make it work. Pretty easy:
self.searchDisplayController.delegate =
self.searchDisplayController.searchBar.delegate =
self.searchDisplayController.searchResultsDataSource =
self.searchDisplayController.searchResultsDelegate = self.mySearchObject;
Controlling how your UISearchBar looks like is a bit more difficult. If you want to show search box and some other component(s) side by side, you can do it by putting UIToolbar at back and a short UISearchBar on top of it. By default their backgrounds are different, looking pretty ugly together. Like a hack, what it really is.

You can fix that by doing two things. First get rid of default background:
for (UIView *view in self.searchBar.subviews)
{
   if ([view isKindOfClass:NSClassFromString
     (@"UISearchBarBackground")])
   {
     [view removeFromSuperview];
     break;
   }
}
...and the second thing? Something that will be extremely hard to find out, unless you get it right by accident? You have to set UISearchBar style Black Translucent!

Sad to think how many hours I wasted experimenting Things That Will Not Work, just to find out that kind of miniscule solution. Also bet that this will not work one year from now...

14 comments:

  1. Hi,

    I have a question regarding the implementation of the actual searching in the data.... while providing the UI part seems to be pretty easy, how do you do the actual search in the data structure (like an NSMtutableArray).... as a search would return a subset of the full data set, how do we indicate that a specific records meet the search criteria and will have to be displayed in the UITableView eventually.... I guess Code Data is way easier in that matter... but without Code Data, what is the general process?

    ReplyDelete
  2. That's why I didn't mention search at all, only search UI :) I do realtime search with a server, so my list content gets totally replaced each time. In other words, I don't filter already existing list. Sorry. Might look at Core Data and NSFetchedResultsController?

    ReplyDelete
  3. Again, I came across your post because I want to customize the SearchBar's background with a different one. I'm using a UISearchBar in a ViewController with a IBOutlet. So I tried this:

    @implementation UISearchBar (CustomBG)
    - (void)drawRect:(CGRect)rect {
    UIImage *image = [UIImage imageNamed: @"NavigationTitleBackground.png"];
    UIView *segment = [searchBar.subviews objectAtIndex:0];
    UIView *bg = [searchBar.subviews objectAtIndex:1];
    segment.hidden=YES;
    bg.hidden=YES;

    [image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
    }
    @end

    But the compiler doesn't know about searchBar ivar... any idea? I'm not sure to understand the meaning of @implementation directive here.. does it tries to override a method?

    ReplyDelete
  4. I've seen such code, when you add new methods to already existing object class. Google for Objective-C category. However drawRect already exists in UISearchBar via UIView, so you just want to overwrite it, not to add as new? Anyway, UISearchBar doesn't have searchBar ivar, guessing self.subviews would be right. Also I would do @interface MyUISearchBar : UISearchBar to overwrite drawRect.

    ReplyDelete
  5. Thanks for posting - this is really useful. Is this App Store-safe? Have you published an app that uses this?

    ReplyDelete
  6. Nope, version 2.0 which is using this got buried under "feature creep". Version 2.1 with iPad support is targeting AppStore next month (I'm in different project now). Could write an update blog post, when it's approved?

    ReplyDelete
  7. I'd be happy to hear after it's approved - I know it's not using private APIs, but I also know that the UISearchBarBackground class isn't documented. Seems like Apple could go either way on this, so I suppose we'll just have to see.

    ReplyDelete
  8. Now it's in App Store, check the 3rd screenshot http://itunes.com/app/chatpoints/

    ReplyDelete
  9. Awesome! Thanks.

    ReplyDelete
  10. Thanks, I was looking for this solution, and it perfectly works for ios 4.3, but not for previous versions.

    ReplyDelete
  11. Weird, since that was coded for 3.1.3!

    ReplyDelete
  12. Hi Jouni,

    I am facing some problem with segment controle in iPad land scape mode, I want the segment controle to be below the searchbar, Can you please sugest me some thing. I tried increasing height of searchBar, Removing segment controle (Not happening) . Please help..!

    ReplyDelete
  13. Segmented control below searchBar, something like the built-in scope bar? https://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/MobileHIG/UIElementGuidelines/UIElementGuidelines.html#//apple_ref/doc/uid/TP40006556-CH13-SW1

    ReplyDelete