Have a little design issue after having upgraded to iOS 5 and Xcode 4.2
This is how my view looked in iOS 4:
1 http://casperslynge.dk/1
And this is how it looks like in iOS 5:
2 http://casperslynge.dk/2
In my navigation delegate I have the following method to draw the "image" at the top:
- (void)drawRect:(CGRect)rect {
UIImage *image;
if(self.barStyle == UIBarStyleDefault){
image = [UIImage imageNamed: #"topbar_base.png"];
}
else{
image = [UIImage imageNamed: #"nyhedsbar_base.png"];
}
[image drawInRect:CGRectMake(-1, -1, self.frame.size.width+3, self.frame.size.height+3)];
}
And inside my controller I set the following:
self.navigationBarStyle = UIBarStyleBlack;
How come it is not working in iOS 5?
Thanks
Under iOS5, you need to use UIAppearance. Have a look at that. Here's an example for using it conditionally so that you can continue to support iOS4:
// iOS5-only to customize the nav bar appearance
if ([[UINavigationBar class] respondsToSelector:#selector(appearance)]) {
UIImage *img = [UIImage imageNamed: #"NavBarBackground.png"];
[[UINavigationBar appearance] setBackgroundImage:img forBarMetrics:UIBarMetricsDefault];
}
As you can see, this sets a custom background image for all UINavigationBars. There are lots of things you can do with UIAppearance. You'll want to keep any custom stuff you're currently doing in drawRect: since pre-iOS4 devices will still use that and not the new UIAppearance code.
Related
I am using the appearance API to customise the look of my UIBarButtonItems.
I currently need to make my buttons look like this:
In iOS5 you have this method which is what I am using:
UIImage *button = [[UIImage imageNamed:#"btn"]
resizableImageWithCapInsets:UIEdgeInsetsMake(3, 3, 3, 3)];
[[UIBarButtonItem appearance] setBackgroundImage:button forState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
But this tiles the non capped portion of the image instead of stretching which gives me this:
iOS 6 has a new method
resizableImageWithCapInsets:resizingMode:
Which lets you specify a 'stretch' resize mode but it is not available for iOS5.
How do I make the button stretch rather than tile the centre of the image for iOS5?
Turns out this is not possible in iOS5, buttons should always use a horizontal style gradient if they are styled since the image will always be tiled. I ended up changing the gradient direction.
You can use the old and deprecated stretchableImageWithLeftCapWidth:topCapHeight: method for iOS5 if you need stretching:
UIImage* (^makeStretchableImage)(UIImage*, CGSize) = nil;
if ([UIImage instancesRespondToSelector:#selector(resizableImageWithCapInsets:resizingMode:)])
{
// If resizableImageWithCapInsets:resizingMode: is available, use it
makeStretchableImage = ^(UIImage* image, CGSize inset) {
return [image resizableImageWithCapInsets:UIEdgeInsetsMake(inset.height, inset.width, inset.height, inset.width) resizingMode:UIImageResizingModeStretch];
};
}
else
{
// Else, we are on an older iOS release, use the deprecated iOS5 method instead
makeStretchableImage = ^(UIImage* image, CGSize inset) {
return [image stretchableImageWithLeftCapWidth:inset.width topCapHeight:inset.height];
};
}
UIImage* stretchableImage1 = makeStretchableImage(originalImage1, CGSizeMake(5,2));
UIImage* stretchableImage2 = makeStretchableImage(originalImage2, CGSizeMake(15,4));
UIImage* stretchableImage3 = makeStretchableImage(originalImage3, CGSizeMake(8,5));
I want to replace the current nav bar with a custom image. How my code is structured is that a tab bar controller controls a bunch of navigation controllers which contain views (tab bar controller -> nav controller -> view). I tried using this code in my app delegate
#implementation UINavigationBar (UINavigationBarCategory)
- (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;
}
#end
But it did not work. Any ideas why? Should I have placed it somewhere else? Thanks!
if you are using iOS 5, you can use setBackgroundImage: like this where ever you initialized the navigation controller (aNavigationController in this example):
[aNavigationController.navigationBar setBackgroundImage:[UIImage imageNamed:#"nav.png"] forBarMetrics:UIBarMetricsDefault];
I would not use a category. I would subclass UINavigationBar instead. See this: https://stackoverflow.com/a/6959354/472344
If you are targeting iOS 5 or up, use #BJH's solution instead.
I'm having some difficulty getting the transparent bits of my png image that I'm using to replace the default status bar to be rendered as transparent in iOS 4.3. At the moment they are coming up black.
Here is the code I'm using to draw my image:
#implementation UINavigationBar (BackgroundImage)
- (void)drawRect:(CGRect)rect
{
UIImage *image = nil;
switch(self.tag)
{
case HeaderBG_Logo:
image = [UIImage imageNamed: #"top_bar_logo.png"];
break;
case HeaderBG_Plain:
image = [UIImage imageNamed: #"top_bar.png"];
break;
}
if(image != nil)
{
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
}
#end
Here is a side by side comparison of the same app running in the simulator in ios4.3 and ios5 (the image has a drop shadow as its bottom border):
As an aside, the 4.3 background image doesn't seem to be rendered as tall as the 5.0 one either.
I've tried setting the UINavigationBar to opaque / setting its background color to clearColor. None of that worked. :(
Can anyone help?
I ended up using the solution from How to create UINavigationBar drop shadow to add a shadow to the UINavigationBar instead.
Just an hint, for iOS 5 you could use the new appreance property to set the background image:
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:#"top_bar.png"] forBarMetrics:UIBarMetricsDefault];
This will set the image for all UINavigationBars in the app.
I am not sure to understand if you are concerned by the status bar or by the navigationBar. According to you question it seems you are more concerned by the Navigation so here is a sample code that worked for me to add a background image for iOS5 and iOS4. It works with transparent png.
Just add this in the loadView method of your viewController:
#define kBackgroundImageTag 42
UINavigationBar *theNavigationBar = self.navigationController.navigationBar;
UIImage *myBackgroundImage = [UIImage imageNamed:#"myImage.png"];
if([theNavigationBar respondsToSelector:#selector(setBackgroundImage:forBarMetrics:)]) //iOS5 stuff
{
[theNavigationBar setBackgroundImage:myBackgroundImage forBarMetrics: UIBarMetricsDefault];
}
else if(![theNavigationBar viewWithTag:kBackgroundImageTag]) //iOS 4 stuff
{
UIImageView *imageView = [[UIImageView alloc] initWithImage:myBackgroundImage];
imageView.tag = kBackgroundImageTag;
[theNavigationBar insertSubview:imageView atIndex:0];
}
Hope it helps !
I am using this code to change the background of my UINavigationBar but it is not showing in the iPhone, but working fine in the iPhone simulator.
self.navigationController.navigationBar.layer.contents = (id)[UIImage imageNamed:#"Blue Bar.png"].CGImage;
Try This
[self.navigationController.navigationBar setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"Your Image Name"]]];
check your image name may be in writing the name of image lowercase letters and upper case letters may validate.
Write a custom class which sets the background.
#implementation MyNavigationBar
- (void)drawRect:(CGRect)rect{
[[UIImage imageNamed:#"navigation.png"] drawInRect:rect];
}
#end
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to add background image on iphone Navigation bar?
I am looking for a way to have a custom navigation bar and need to have a custom navigation bar background to achieve this. I was looking around for how to do this, but could not find a solution. If anyone has the solution, help is much appreciated.
Since iOS5, you can easily set a custom background, with the method setBackgroundImage:forBarMetrics:
But you must check if the user's phone has the right OS.
if ([self.navigationController.navigationBar respondsToSelector:#selector(setBackgroundImage:forBarMetrics:)])
{
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:#"texture.png"]
forBarMetrics:UIBarMetricsDefault];
}
This is a nicer solution, cause it's in the doc.
(supplemental to Andrew Johnson's response)
The linked Apple.com post includes 3 or 4 different solutions, most of which only "half" work. I think the most elegant/effective of them is this one:
#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
HOWEVER ... it's not good-practice ObjC to od that as a category (should be an override), and it has some problems of its own.
So, a more general and powerful solution is here:
http://samsoff.es/posts/customize-uikit-with-method-swizzling
You can just add a subview (a UIImageView) to the navaigationBar, which is just a UIView subclass.
UINavigationBar nb = [[UINavigationBar alloc]init];
[nb addSubview: foo];
[nb release];
Here's a forum post that describes how to wrap this up into a category: http://discussions.apple.com/thread.jspa?threadID=1649012&tstart=0
Copy this into viewDidLoad. It will check for iOS 5 and use the preferred method, otherwise it will add a subview to the navBar for iOS versions < 5.0. This will work provided that your custom background image has no transparencies.
float version = [[[UIDevice currentDevice] systemVersion] floatValue];
NSLog(#"%f",version);
UIImage *backgroundImage = [UIImage imageNamed:#"myBackgroundImage.png"];
if (version >= 5.0) {
[self.navigationController.navigationBar setBackgroundImage:backgroundImage forBarMetrics:UIBarMetricsDefault];
}
else
{
[self.navigationController.navigationBar insertSubview:[[[UIImageView alloc] initWithImage:backgroundImage] autorelease] atIndex:1];
}