navigationbar 的背景颜色和图片(老外的博客)

UINavigationBar with solid color or image background

How about a nice navigation bar without default iPhone gradient or with a beautiful background image? Lets do it! The thing we’re going to do in both sub-solutions is to override UINavigationBar drawRect function with a help of category. As you may or may not know categories helps us to add additional functionality to an existing classes even if we can’t access their source directly. For more information readExtending Classes in Objective-C With Categories.

UINavigationBar category

First, as I mentioned before, lets override drawRect method with our own. I usually drop this code at the bottom of my application delegate, but you may want to be more organized than that.

?
1
2
3
4
@implementation UINavigationBar (UINavigationBarCategory)
- ( void )drawRect:(CGRect)rect {
}
@end

At this point if you run your application (just don’t forget to actually have UINavigationController with visible navigation bar in it) navigation bar will look like.. em.. black rectangle. It means we successfully taken over the control of it’s drawing method and can move further.

Solid color background

So I’ve heard you hate gradients? Since, we’ve already have UINavigationBar in our hands, we can draw a rectangle over it. A nice gray rectangle! Enough of gray already? Okay, red rectangle it will be..

?
1
2
3
4
5
6
- ( void )drawRect:(CGRect)rect {
UIColor *color = [UIColor redColor];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColor(context, CGColorGetComponents( [color CGColor]));
CGContextFillRect(context, rect);
}

And just look at our results! Amazing!

But aren’t we forgetting something? We’re not done here yet. Remember that iPhone uses UINavigationBar property tintColor to style buttons in navigation bar, so unless we want blue buttons in red background (just think about poor eyes of your application users!) we need to alter our code a little bit.

?
1
2
3
4
5
6
7
- ( void )drawRect:(CGRect)rect {
   UIColor *color = [UIColor redColor];
   CGContextRef context = UIGraphicsGetCurrentContext();
   CGContextSetFillColor(context, CGColorGetComponents( [color CGColor]));
   CGContextFillRect(context, rect);
   self.tintColor = color;
}

Background image

Using image for UINavigationBar background is even more simple! In this example I’ll use 320×44 custom image which also displays my drawing skills.

?
1
2
3
4
5
6
- ( void )drawRect:(CGRect)rect {
   UIColor *color = [UIColor blackColor];
   UIImage *img  = [UIImage imageNamed: @ "nav.png" ];
   [img drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
   self.tintColor = color;
}

Some important things to have in mind: decide what color of buttons suits your background best, keep in mind iPhone dimensions while drawing your background image and don’t forget about landscape mode if your application is going to support it.

55 responses

  1. sam
    Posted February 12, 2010 at 10:13  |  Permalink

    Hi
    Thanks for that beautiful article. it just solved one of my issues :) .. do you know if there is a way to remove the glossy effect of the buttons as well?
    cheers

    sam

  2. Bobo
    Posted February 22, 2010 at 19:56  |  Permalink

    Hi

    Thank you for the great article. I have few viewcontrollers and I want navigation bar to have different color on each controller. How to accomplish this.

    Thank you

    • Foobar Pig
      Posted February 22, 2010 at 23:34  |  Permalink

      Okay, I think it’s actually possible. Use drawRect code above to “paint” your UINavigationBar, but use some kind of global color variable or class, so you’ll be able to set/get it, and then, in ViewDidAppear methods of your navigation controllers, set that color to whatever you like and “refresh” your navigation bar like this:

      UINavigationBar *bar = [self.navigationController navigationBar];
      [bar setNeedsDisplay];

      *setNeedsDisplay will initiate redrawing of your navigation bar (drawRect will be called again)

      It should work. Good luck!

      • Deepak Jangra
        Posted September 22, 2011 at 06:01  |  Permalink

        Hi,
        I was using the same approach in the iOS 4.3.3 version and it was working fine. But when I upgrade my machine on the iOS 5, then this method stop working. I tried to called the setNeedsDisplay method for the navigationBar but nothing happened and drawRect method did not called. Please suggest me the way to accomplish this feature in iOS 5.

        Thanks in advance

        • Eric
          Posted October 5, 2011 at 22:55  |  Permalink

          Ran into the same problem, I surmise they broke some stuff with os5, but they’ve also added framework support for changing the image:
          - (void)setBackgroundImage:(UIImage *)backgroundImage forBarMetrics:(UIBarMetrics)barMetrics

  3. Erik
    Posted May 20, 2010 at 04:35  |  Permalink

    Great article. I have the need to draw a background image or set a tint color on a navigation bar, but I also need to support doing neither. If my app does not have a background image, what can I do instead to ensure the drawRect method does it normally would do?

    I.E. -

    @implementation UINavigationBar (UINavigationBarCategory)
    - (void)drawRect:(CGRect)rect {
    if(hasImage){
    UIImage *img = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://myimageurl.com/img.jpg"]]];
    [img drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
    }else{
    ??????
    }
    }
    @end

  4. Ayaz
    Posted June 2, 2010 at 08:29  |  Permalink

    Hi,
    Excellent article you finally taught me how to use drawrect method. Can u explain why you used UINavigationBarCategory in the implemenation line or point me to documentation that explains how to do that for other UIcontrols also.
    I am creating theme for my app that is xml based and will be stored in a themes folder of my app. i need to traverse that file and apply theme that does exaclty same i.e set navigation bar styles, tabbar styles etc. What might be best possible solution for doing this? i have got about 7-8 viewcontrollers that needs to be applied that theme on app launch or viewdidload method. Any suggestion would be great.

  5. paula
    Posted June 8, 2010 at 12:59  |  Permalink

    Hi,
    Thanks for the post, the information was very useful.
    best regards.

  6. Posted July 14, 2010 at 11:31  |  Permalink

    Hey wow, thanks for this!
    If you leave the drawRect method empty and have transparency on for the NavigationBar you can have an invisible navigation bar but the buttons still show up when moving around. Which is just what I needed!! (Since if you just try setting alpha to 0, the buttons disappear as well).

    much appreciated.

  7. Phlibbo
    Posted September 12, 2010 at 15:34  |  Permalink

    Even though this works with categories, it’s highly unadvisable to use them. You should rather use subclasses.

    Taken from the Apple Objective C Reference Library:
    “Although the language currently allows you to use a category to override methods the class inherits, or even methods declared in the class interface, you are strongly discouraged from using this functionality. A category is not a substitute for a subclass.”

    See:http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/objectivec/articles/occategories.html

    • Paul
      Posted October 10, 2010 at 23:31  |  Permalink

      So how would you do this with subclassing? Would it work to subclass the NavBar and from your subclass change the colors?

      Foobars approach is really quite simple.

      • Phlibbo
        Posted October 29, 2010 at 18:19  |  Permalink

        Subclassing uses pretty much the same approach, you create a subclass of UINavigationBar and define your own drawRect, that’s it. This way, you have a) code that doesn’t violate the programming guidelines and b) preserved the possibility to access drawRect of the superclass which might come in handy, in case apple changes this class.

        • Pravat
          Posted February 16, 2011 at 06:05  |  Permalink

          @implementation UINavigationControllerEx

          -(id) init{
          if(self=[super init]){
          UINavigationBarEx *navigationBarEx = [[UINavigationBarEx alloc] init];
          self.navigationBar = newNavagitionBar;
          }
          return self;
          }

          I cannot do this,
          navigationBar is readOnly property,
          then how to achieve this by using SubClass?

    • Barry
      Posted October 19, 2010 at 06:14  |  Permalink

      The reason for not doing this in a category is that you may not be the only category declared on that class. If someone else’s code, say a library, does the same thing it becomes undefined and you no longer know who’s code will be called.

      The old school way of doing this is to use class_replaceMethod, (#import ) but of course your code could be replaced just as easily. Also it is not clear to me whether or not your App will get rejected for using that call. Until Apple provides an easy method for subclassing the navigation bar, categories will have to suffice.

      • Barry
        Posted October 19, 2010 at 06:15  |  Permalink

        That was an #import of objc/runtime.h which got stripped because of the gt and lt.

  8. Posted September 19, 2010 at 12:25  |  Permalink

    Gday, This approach is actually cool

  9. erik
    Posted September 20, 2010 at 18:52  |  Permalink

    You rock!

  10. Louisdd
    Posted October 15, 2010 at 09:01  |  Permalink

    thanks a lot man, you just saved (part) of my life :)

  11. Posted November 4, 2010 at 22:14  |  Permalink

    Hi, nice work. But do you know how to do the opposite? I want to tint my UIButtons like those UIBarButtonItems on UINavigationBar.

  12. Posted November 24, 2010 at 21:56  |  Permalink

    Thank you for this great tutorial!

  13. Posted March 6, 2011 at 18:36  |  Permalink

    Just want to ask, how to subscribe via iphone? Cause I always outdoor all the time. Your blog is a source of decent materials, I really like read it when I waiting for something.

  14. Sandy
    Posted March 10, 2011 at 13:07  |  Permalink

    Very valuable info…helped a lot…thanks a ton.

  15. Nattapon
    Posted March 19, 2011 at 09:19  |  Permalink

    Thank you alot.
    Your Solution’s very helpful.
    Only 10 minutes I can custom my bar by your way.

    Thank for sharing

  16. Posted March 27, 2011 at 13:01  |  Permalink

    Thanks so much for giving me an update on this subject matter on your website. Please realise that if a fresh post appears or in case any modifications occur about the current submission, I would be considering reading more and finding out how to make good utilization of those approaches you reveal. Thanks for your time and consideration of people by making this blog available. Phone Cards

  17. Posted March 27, 2011 at 21:21  |  Permalink

    Even marriage can be handled with concerted attempt and dedication, such a lot marriages have turn into a significant issue, please spend some time boring. Whilst bearing in mind the issue of marriage, it’s simply ahead of taking any motion.

  18. Posted April 3, 2011 at 05:22  |  Permalink

    I just couldn’t depart your website before suggesting that I really enjoyed the standard info a person provide for your visitors? Is gonna be back often in order to check up on new posts

  19. Posted April 8, 2011 at 07:03  |  Permalink

    Outstanding – I should really certainly pronounce, impressed with your site. I had no difficulty navigating by means of all the tabs also as linked info ended up being really simple to perform to entry. I lately discovered what I hoped for just before you realize it whatsoever.

  20. Posted April 9, 2011 at 08:11  |  Permalink

    I got what you intend, saved to fav, very nice site.

  21. Posted April 13, 2011 at 05:28  |  Permalink

    me gusta muchisimo tu pagina

  22. Hesham Abd-Elmegid
    Posted April 14, 2011 at 12:31  |  Permalink

    Thanks. That was helpful, although I created a subclass of UINavigationBar instead of creating a category.

  23. Posted May 23, 2011 at 01:25  |  Permalink

    59. Thank you for another informative site. Where else could I get that type of info written in such a perfect way? I’ve a project that I am just now working on, and I’ve been on the look out for such information.

  24. Posted May 24, 2011 at 23:22  |  Permalink

    Would you mind basically pages and use a number of your posts so long as I provide credit and sources to your internet site? My blog site is incorporated in the identical area of interest as yours and my visitors would genuinely reap the benefits of most of the information you provide here. Please inform me if the alright with you. Thanks a whole lot!

  25. Posted May 26, 2011 at 12:54  |  Permalink

    It’s exhausting to find educated folks on this matter, however you sound like you understand what you’re speaking about! Thanks

  26. Posted May 28, 2011 at 19:38  |  Permalink

    Hello my family member! I want to say that this article is awesome, nice written and come with almost all vital infos. I¡¦d like to peer extra posts like this .

  27. ad34
    Posted June 7, 2011 at 13:04  |  Permalink

    Hello,

    Amazing but….

    We also want tutorial to change label color, We want it black ;)

  28. Rob
    Posted June 11, 2011 at 20:36  |  Permalink

    Hmm. I have been successfully doing something like this, but it doesn’t appear to work in iOS 5. Any suggestions?

  29. Rob
    Posted June 11, 2011 at 20:47  |  Permalink

    Looks like it only works in iOS 5 if you subclass the UINavigationBar, not if you employ a category on UINavigationBar itself.

  30. Phlibbo
    Posted June 19, 2011 at 20:30  |  Permalink

    Oh, what a surprise, my predictions from my previous post where correct. As I said, the category-method is faulty anyway, the usage of subclasses, as Ron suggests, is your best bet.

  31. Corey
    Posted June 27, 2011 at 23:14  |  Permalink

    Anyone know how to do this for a UIToolbar?

  32. EricS
    Posted July 18, 2011 at 15:18  |  Permalink

    Subclassing does not work easily because, as someone mentioned, the navigationBar property is read-only. One workaround to this problem is to create the nav bar in your xib file instead of programmatically. You can change the class type there.

  33. Posted August 12, 2011 at 19:51  |  Permalink

    That is a beneficial mindset, however isn’t produce virtually any sence whatsoever talking about of which mather. Just about any approach thank you and i had try to talk about a person’s publish straight into delicius but it surely is apparently a dilemma with all your blogging is it possible to make sure you recheck them. with thanks just as before.

  34. Posted August 19, 2011 at 22:49  |  Permalink

    AGpTIUGl Cheap

  35. Posted September 30, 2011 at 13:59  |  Permalink

    Here is an alternative solution that lets you use your own custom subclass of UINavigationBar:

    https://gist.github.com/1253807

    • ggg
      Posted November 8, 2011 at 14:43  |  Permalink

      this doesn’t work!
      and I’m not sure it’s Appstore safe.

  36. Deathmate
    Posted October 3, 2011 at 04:24  |  Permalink

    I use the category method myself, but as others have pointed out this is not supported in iOS 5.

    Now discussing iOS 5 outside of apples approved forums is against the developers license, however those with access to the iOS 5 docs I strongly suggest you have a look at the UINavigationBar reference. You might find something that will make this a lot easier.

  37. Posted December 13, 2011 at 01:56  |  Permalink

    On iOS 4.3 & simulator 4.3, this causes the navbar to become transparent, discussed here:
    http://stackoverflow.com/questions/6783061/disappearing-navigationbar-color-in-ios-4-3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值