I have implemented a custom UINavigationbar using this code (placed in the top of my AppDelegate.m file):
#implementation UINavigationBar (CustomImage)
- (void)drawRect:(CGRect)rect {
UIImage *image = [UIImage imageNamed: #"NavigationBar.png"];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
#end
And it works great! The problem is, when I push a particular class of view controller, I would like to remove the custom navigationbar and show the standard one (or alternatively change the NavigationBar.png).
But I can't figure out how to do this, and googling isn't really helping.
Has anyone done this?
Many thanks,
Brett
Rather than use the drawRect override, place this bit of code in each view controller inside the navigation controller. Then just change the image that is used in each view controller you want it to be different:
self.navigationController.navigationBar.layer.contents = (id)[UIImage imageNamed:#"NavigationBar.png"].CGImage;
You will have to include Quartz core, so include this line in the imports of your view controllers header file:
#import <QuartzCore/QuartzCore.h>
Related
I'm using Xcode 4.4.1 and iOS 5.
I have set the Navigation bar for several viewcontrollers using the storyboard.Now I want to set a background image for all those navigationbars.
so in my AppDelegate.m I put this,
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
UIImage *naviImg=[UIImage imageNamed:#"first.png"];
[[UINavigationBar appearance]setBackgroundImage:naviImg forBarMetrics:UIBarMetricsDefault];
}
But it not changes any thing in any Viewcontroller's navigationbar.
Can any one tell me how to do that, I'm very new to iOS development.
Thanks
Firstly,set the IBOutlet for the navigation bar in the viewController.h where you want to change the image.
IBOutlet UINavigationBar *navigationBar;
Then in viewDidLoad write this code,
[self.navigationBar setBackgroundImage:[UIImage imageNamed:#"wall.jpg"] forBarMetrics:UIBarMetricsDefault];
I know I can change the tint color of navigation bar in xib file easily. But the problem is that if i have to change in a lot of places.
Hence i tried using the (fancy) category and overriding the draw rect method.
#import "UINavigationBar+customTint.h"
#implementation UINavigationBar (customTint)
-(void)drawRect:(CGRect)rect{
self.tintColor = [UIColor redColor];
}
#end
I have imported it in the corresponding view controller as well. What am i doing wrong?
Whats the right way of doing it?
THanks in advance
That is one way of doing it. It would probably just be easier in you ViewController where ever you need to change it add the line:
self.navigationController.navigationBar.tintColor = [UIColor redColor];
Using a category for just one line is probably overkill.
EDIT:
If you do want to use a category, you may need to call setNeedsDisplay on the navigation bar. or override another method and call it.
Something like ,
[self.navigationController.navigationBar setNeedsDisplay];
Also according to Apple's documentation
In iOS 5, the UINavigationBar, UIToolbar, and UITabBar implementations have changed so that the drawRect: method is not called unless it is implemented in a subclass. Apps that have re-implemented drawRect: in a category on any of these classes will find that the drawRect: method isn't called. UIKit does link-checking to keep the method from being called in apps linked before iOS 5 but does not support this design on iOS 5 or later.
Apps can either:
Use the customization API for bars in iOS 5 and later, which is the preferred way.
Subclass UINavigationBar (or the other bar classes) and override drawRect: in the subclass.
The best way to therefore go about this would be to place this in your ApplicationDidFinishLaunching
NSString *reqSysVer = #"5.0";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending)
[[UINavigationBar appearance] setTintColor:myColor];
And also leave your DrawRect, so that it will work on iOS less than 5
If you're using iOS5 then the correct way to do it is to use the UIAppearance proxy.
[[UINavigationBar appearance] setTintColor:myColor];
Details here: https://developer.apple.com/library/ios/#documentation/uikit/reference/UIAppearance_Protocol/Reference/Reference.html
I have a category to display a custom image in an app's UINavigationBar. When the app comes back from the background the image sometimes disappears and all I am left with is a white navigation bar with buttons.
The category I'm using is below, can anyone advise please?
#implementation UINavigationBar (CustomImage)
-(void)drawRect:(CGRect)rect {
cardSmartAppDelegate *delegate = (cardSmartAppDelegate *)[[UIApplication sharedApplication] delegate];
[delegate.navImage drawInRect:rect];
}
#end
You shouldn't use a category to override a method. Sometimes it works, but often it doesn't. Rumor has it that it will quit working altogether soon.
See my code in this item for how to do what you want:
Custom UINavigationBar Background
I have a Universal App in which I customize my UINavigationBar.
In my iPhone AppDelegate I use this to achieve it:
#implementation UINavigationBar (CustomImage)
static NSMutableDictionary *navigationBarImages = NULL;
- (void)initImageDictionary
{
if(navigationBarImages==NULL){
navigationBarImages=[[NSMutableDictionary alloc] init];
}
}
- (void)drawRect:(CGRect)rect
{
NSLog(#"drawing navbar2");
UIImage *imageName=[navigationBarImages objectForKey:[NSValue valueWithNonretainedObject: self]];
if (imageName==nil) {
imageName=[UIImage imageNamed:#"bg_titleBar.png"];
UIImage *image = imageName;
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
}
- (void)setMyImage:(UIImage*)image
{
[navigationBarImages setObject:image forKey:[NSValue valueWithNonretainedObject: self]];
[self setNeedsDisplay];
}
#end
Now my questions: why does this code get called, although I start the iPad simulator?
And more important it seems to corrupt the UIPopoverController because it looks like this:
http://awesome-apps.com/pic/ok.png
While it should look somehow like this:
http://awesome-apps.com/pic/nok.png
Besides it corrupts more in my App, but this should be it for starters :)
Can anyone help me with this? Have you ever had a similar experience?
So ignore the fact that it gets called when you run in the iPad simulator, because as you'll see in a minute even if you used two different categories (one for iPhone, one for iPad) you'd still have this problem.
Here's why:
You are using a category to override the UINavigationBar behaviour. I assume you know what that means - crucially any and all navigation bars in your app will use your supplied methods in the category.
This can cause problems if you're using standard apple elements that use UINavigationBars - the exact thing you're seeing in the popover controller. What's happening is the UIPopoverController uses a UINavigationBar. But because you've defined a category, the app assumes you want the popover navbar to use that category as well.
So that's why you're seeing your weird behaviour in your pop-over controller.
As long as you use categories you'll have this problem, because you can't selectively tell the system which bars should use your category.
I'd suggest you tell us exactly you're trying to customise in the navbar, because there are other ways to achieve customisation outside of categories.
I have a NavigationController with customized UINavigationBar:
#implementation UINavigationBar (CustomImage)
- (void)drawRect:(CGRect)rect
{
UIImage *image = [UIImage imageNamed: #"banner.png"];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
#end
I'm allowing rotation using shouldAutorotateToInterfaceOrientation.
When i'm rotating, i would like to change the banner.png with banner_port.png
How can i do it?
[UIDevice currentDevice].orientation will tell you which way the device thinks it is...
you can do an if or switch at that point on the value it gives you.
You can make your navigation bar object to listen global UIDeviceOrientationDidChangeNotification, which has property 'orientation', and make necessary changes, when event occurs.
See also Custom UINavigationBar Background
I agree wit with Dave DeLong - overriding drawRect isn't wise, it may break some day. Plus, your category's drawRect replaces the original drawRect -- you don't have the option of calling super to get default functionality.
Note that if you listen for changes to UIDeviceOrientationDidChangeNotification, you need to be aware that there are six device orientations (the usual four, plus face up and face down).
Poorly written code is often seen which doesn't acknowledge the possibility of face up and face down device orientations.
N.B. you can also access the user interface's current status bar orientation - which isn't necessarily the same as the UIDeviceOrientation!