UINavigationBar with solid color iOS 5 - ios5

I'm using the category to customize nav bar. My code is:
- (void) drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColor(context, CGColorGetComponents([self.tintColor CGColor]));
CGContextFillRect(context, rect);
}
It works well, but not in iOS 5. I need nav bar color to be solid without any gradient. How should I do this?
As I know, for iOS 5 the only way to replace drawRect method is to make a subclass, but is there any way to make all navigation controllers to use UINavigationBar subclass instead of original class?

In iOS 5 you can use the UIAppearance protocol to set the appearance of all UINavigationBars in your app. Reference: link.
The way I got a solid color was to create a custom image for the navigation bar, and set it as UINavigationBars background. You might have to create the image with the same size as the UINavigationBar, at least that's what I did.
In your app delegate, do something like this:
UIImage *image = [UIImage imageNamed:#"navbarbg.png"];
[[UINavigationBar appearance] setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];
You also have to add the UIAppearanceContainer protocol to the header file:
#interface AppDelegate : UIResponder <UIApplicationDelegate, UIAppearanceContainer>
#end
You can probably achieve the same thing by setting some color or something, instead of an image. But I found this to be an easy solution.

This covers both iOS 5 and iOS 4.3 and earlier
https://gist.github.com/1774444

This is more of a hack and has consistently worked for me.
This needs to be in the AppDelegate file.
//Create a size struct.
CGSize size = CGSizeMake(768, 50);
//CReate a imagecontext from a non-existing image. You can use a existing image as well, in that case the color will be the color of the image.
UIImage *backgroundImage = [UIImage imageNamed:#"nonexist.png"];
UIGraphicsBeginImageContext(size);
[backgroundImage drawInRect:CGRectMake(0,0,size.width,size.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.navigationController = [[UINavigationController alloc]initWithRootViewController:self.viewController];
Set the background color to be the color of your choice.
[self.navigationController.view setBackgroundColor:[UIColor blackColor]];
self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
//Most important line.
[navigationController.navigationBar setBackgroundImage: newImage forBarMetrics:UIBarMetricsDefault];

Related

Setting shadowImage On Translucent Navigation Bar

I am trying to set the shadowImage of the navigaion bar in my app delegate:
[[UINavigationBar appearance]setShadowImage:[UIImage imageNamed:#"navigation-bar-shadow"]];
This does not work by itself. It only works if I set the background image of the navigaion bar as well:
[[UINavigationBar appearance]setBackgroundImage:[UIImage new]forBarPosition:UIBarPositionAny barMetrics:UIBarMetricsDefault];
Here is my problem... the navigation bar is transluncent and I would like to keep it that way (no background images). But it seems that I cant set the shadowImage without setting the background image.
How can I set the shadowImage on translucent navigation bar?
Thanks!
Yes, you cannot set a shadowImage of a navigationBar without setting its backgroundImage :
See UINavigationBar Documentation :
For a custom shadow image to be shown, a custom background image must
also be set with the setBackgroundImage:forBarMetrics: method.
But you can render shadowImage invisible with empty image :
[[UINavigationBar appearance] setShadowImage:[[UIImage alloc ]init]];
The response marked as an answer does not work if you want to keep the translucent effect in the NavigationBar.
A workaround I did was:
1) Create an Image with the color I wanted:
CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [[UIColor blueColor] CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
Then I assigned this as the backgroundImage to the UINavigationBar
[[UINavigationBar appearance]setShadowImage:[[UIImage alloc] init]];
[[UINavigationBar appearance]setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];
Note that this makes the navigation bar fully transparent. Then I did the following to mimic the translucent 'blur' effect:
UIView *obfuscateView = [[UIView alloc] initWithFrame:CGRectMake(0,0,64,self.view.frame.width)];
[obfuscateView setBackgroundColor:[UIColor blueColor]];
[obfuscateView setAlpha:0.9f];
[self.view addSubView:obfuscateView];
The main thing here is you need to now add an additional view behind the navigationBar that will mimic the blur effect. This can be achieved with a minimal hit to performance by playing with alpha transparency rather than actually doing the calculations using a blurring view. Also note that this UIView needs to be of the same color.
What this allows you to do though is also play with gradients that have varying alpha to create a fading effect into the nav bar.

How to programmatically render a flat background UIColor as the background for a UIToolbar?

So I followed a tutorial which allows me to subclass UIToolbar and draw an image as a custom background for the UIToolbar.
Code was something like this:
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
UIImage *backgroundImage = [UIImage imageNamed:#"toolbar_background.png"];
[backgroundImage drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
This works flawlessly. Considering though that I just want my toolbar background to be a flat color. Basically something like [UIColor blackColor], is there an easier way to do this in the drawRect method?
Having to make a 320 x 44 px height flat black background image and use that with the above code seems like extreme overhead when [UIColor blackColor] is available? I'm just not sure how to implement it here.
I thought about doing something like this instead:
- (void)drawRect:(CGRect)rect
{
UIView *test = [[UIView alloc] initWithFrame:CGRectMake(0,0,self.frame.size.width,self.frame.size.height)];
test.backgroundColor = [UIColor blackColor];
[self addSubview:test];
}
But this doesn't work because then the UIView COVERS all the UIToolbar items that I add later i.e the Toolbar is black yes, but the black is overtop all the toolbar items so they are not visible.
Is there a workaround?
Thanks.
You can create a flat UIToolbar without the need to create a subclass. Simply set BackgroundColor, BackgroundImage and ShadowImage.
[toolbar setBackgroundColor:[UIColor blackColor]];
[toolbar setBackgroundImage:[[UIImage alloc] init] forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
[toolbar setShadowImage:[[UIImage alloc] init] forToolbarPosition:UIToolbarPositionAny];
Override the -drawRect: method as in your first example, but instead of drawing an image, use the UIRectFill method, like this:
[[UIColor blackColor] setFill];
UIRectFill(self.bounds);

change background color of navigation item (bar)

is there an easy way to change the background color of the navigation item on top of a view? I have a navigation based app and I only want that one view gets another background color. I created the views mainly with IB. I found the following solution (not tested):
float r=10;
float g=55;
float b=130;
float a=0;
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 120, 30)];
[label setBackgroundColor:[UIColor colorWithRed:r/255.f
green:g/255.f
blue:b/255.f
alpha:a/255.f];];
[self.navigationController.navigationBar.topItem setTitleView:label];
[label release];
Is there an easier way like
[navigationController.navigationBar setBackgroundColor:blueColor]
Or can I do it with IB (but without having the same color in every view)?
Many thanks in advance!
Cheers
You could use:
[navigationController.navigationBar setTintColor:[UIColor redColor]; //Red as an example.
This would tint the color of the Navigation Bar and all it's Buttons to a specific color, in this case red. This property can also be set in Interface Builder.
And if you wanted to customize it further, you can set the background of the UINavigationBar to an image by sub-classing it. Like so…
Header File.
#import <UIKit/UIKit.h>
#interface UINavigationBar (CustomImage)
#end
Implementaion File.
#import "CustomNavigationBar.h"
#implementation UINavigationBar (CustomImage)
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
if([self isMemberOfClass: [UINavigationBar class]]){
UIImage *image = [UIImage imageNamed:#"bar.png"];
CGContextClip(ctx);
CGContextTranslateCTM(ctx, 0, image.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);
CGContextDrawImage(ctx, CGRectMake(0, 0, self.frame.size.width, self.frame.size.height), image.CGImage);
}else{
[super drawLayer:layer inContext:ctx];
}
}
#end
Then in Interface Builder set the class of you UINavigationBar to (in this case) CustomNavigationBar under the Identity Tab.
Try this in Interface Builder on your UINavigationController.
[[UINavigationBar appearance] setTintColor:[UIColor colorWithRed:107.0/256.0 green:145.0/256.0 blue:35.0/256.0 alpha:1.0]];
Will change the color of the navigation bar of whole app.
Just place it in Appdelegate's didFinishLauncing method.
You can use navigationController.navigationBar.tintColor;
#jerry
tint color is not supported to the RGB Coordinates

iPhone Navigation Bar Images

I'd like to replace the back button and the entire navigation bar in my iPhone app with custom images. First of all, is this possible? Second, if so, how? Thanks.
This code will modify every UINavigationBar in your app.
#implementation UINavigationBar (CustomImage)
- (void)drawRect:(CGRect)rect {
UIImage *image = [UIImage imageNamed: #"MyNavigationBar.png"];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
#end
You won't be able to override the look and feel of Apple's navigation bar easily, and even if you are able to, there's a good chance it will go against their policy of avoiding private API's. However, it is pretty simple to create your own look-alike navigation bar using all custom images. This would work well for simple one-off screens that need the navigation bar, but will be a beast to implement on a complex UINavigationController-based hierarchy.
Edit: It looks like people have been able to change the background by overriding the -drawRect selector: Custom background for UINavigationBar? . I don't see any reports of whether or not the changes were approved for the App Store.
You can use this code to change navigation bar image and tab bar image to your custom images:
if([[UINavigationBar class] respondsToSelector:#selector(appearance)]) {//iOS >=5.0
UIImage *image = [UIImage imageNamed:#"myCustomImage.png"];
CGSize newSize = CGSizeMake(self.navigationController.navigationBar.frame.size.width, self.navigationController.navigationBar.frame.size.height);
UIGraphicsBeginImageContext(newSize);
[image drawInRect: CGRectMake(0, 0, self.navigationController.navigationBar.frame.size.width, self.navigationController.navigationBar.frame.size.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self.navigationController.navigationBar setBackgroundImage:newImage forBarMetrics:UIBarMetricsDefault];
[[UIToolbar appearance] setBackgroundImage:newImage forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
[[UITabBar appearance] setBackgroundImage:newImage];
[[UITabBar appearance] setSelectedImageTintColor:[UIColor cyanColor]];
}

using image or tint color on uinavigationbar in iphone?

how do i show a background image on a navigation bar or give tint color to the navigation bar in a native iphone application??
For iOS5 use the following lines of code:
UINavigationBar *navBar = [[self navigationController] navigationBar];
UIImage *backgroundImage = [UIImage imageNamed:#"nav-bar-background-normal"];
[navBar setBackgroundImage:backgroundImage forBarMetrics:UIBarMetricsDefault];
For backward compatibility do a check to see if the navigation bar responds to setBackgroundImage:forBarMetrics:
More information on:
http://sebastiancelis.com/2009/12/21/adding-background-image-uinavigationbar/
This's how I did on iOS4:
#import <QuartzCore/QuartzCore.h> // For .layer
self.navigationController.navigationBar.layer.contents = (id)[UIImage imageNamed:#"navigationBarBackgroundImage"].CGImage;
self.navigationController.navigationBar.tintColor = [UIColor orangeColor];
No need to switch subviews between z-orders (-exchangeSubviewAtIndex:withSubviewAtIndex:), both background image and tintColor set in one line of code, and works with #2x image too.
Was looking for this a week ago. Found this over here discussions. apple. com/thread.jspa?threadID=1649012&tstart=0 (sorry won't let me post a real link).
-(void)setBackgroundImage:(UIImage*)image withTag:(NSInteger)bgTag{
if(image == NULL){ //might be called with NULL argument
return;
}
UIImageView *aTabBarBackground = [[UIImageView alloc]initWithImage:image];
aTabBarBackground.frame = CGRectMake(0,0,self.frame.size.width,self.frame.size.height);
aTabBarBackground.tag = bgTag;
[self addSubview:aTabBarBackground];
[self sendSubviewToBack:aTabBarBackground];
[aTabBarBackground release];
}
/* input: The tag you chose to identify the view */
-(void)resetBackground:(NSInteger)bgTag {
[self sendSubviewToBack:[self viewWithTag:bgTag]];
}
I made this as a category to UINavigationBar. To set it a background image for a UINavigationBar inside a UINavigationBarController, I did this:
[navigationControllerForChannels.navigationBar setBackgroundImage:[UIImage imageNamed:#"top_bar.png"] withTag:48151623];
I've had some buginess when updating the tab bar, so you'll want to call
[self.navigationController.navigationBar resetBackground:48151623];
After any modifications to the bar.
You can override UINavigationBar drawRect. The code can be placed to appDelegate.m
I've tested it and it's working on 3x and 4x iOS.
#implementation UINavigationBar (UINavigationBarCategory)
- (void)drawRect:(CGRect)rect {
UIColor *color = [UIColor blackColor]; //tint color
UIImage *img = [UIImage imageNamed: #"navBarBg.png"]; // your image
[img drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
self.tintColor = color;
}#end
For the iOS5 and iOS6 I've used this solutions and it worked perfectly, Making a Universal UINavigationBar Background Image.
iPhone Retina Portrait 640px x 88px / iPhone Non-Retina Portrait 320px x 44px
Inside AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
Place this code
// Set the status bar to black color.
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque animated:NO];
// Change #"menubar.png" to the file name of your image.
UIImage *navBar = [UIImage imageNamed:#"menubar.png"];
[[UINavigationBar appearance] setBackgroundImage:navBar forBarMetrics:UIBarMetricsDefault];
Don't forget to change the image name (menubar.png)
Check out this link for the full answer http://www.lwxted.com/blog/2012/add-custom-background-image-uinavigationbar-ios-5/
a background image is going to take a bit more work (you might want to try setting a titleView that's the same size as the bar itself; I haven't tried this myself) or adding a view behind existing subviews. Tint color is easy: navBar.tintColor = [UIColor orangeColor];
If you use the CGImage solution, you may have a problem with image size:
CGRect layer=self.navigationController.navigationBar.frame;
layer.size.height=57.0;
layer.origin.y=0;
self.navigationController.navigationBar.frame=layer;
CGImageRef imageRef = [UIImage imageNamed:#"myImg.png"].CGImage;
self.navigationController.navigationBar.layer.contents = (id)imageRef;
It seems to me that the image is streched down, since the layer seems to have a height of 44.0 pixel, but a background image for the UINavigationBar should be at least 57.0.
If you try to move the layer's frame, all the buttons will move within it.