I am having problems with properly displaying background image of navigation view.
Here is the pic:
Here is the code:
- (id)initWithStyle:(UITableViewStyle)style {
if (self = [super initWithStyle:style]) {
UIImage *image = [UIImage imageNamed: #"bg_table_active.png"];
UIImageView *imageview = [[UIImageView alloc] initWithImage: image];
UIBarButtonItem *addButton = [[UIBarButtonItem alloc]
initWithTitle:NSLocalizedString(#"Settings", #"")
style:UIBarButtonItemStyleDone
target:self
action:#selector(GoToSettings)];
self.navigationItem.titleView = imageview;
self.navigationItem.rightBarButtonItem = addButton;
self.navigationItem.hidesBackButton = TRUE;
}
return self;
}
How can I make the picture stretch to the whole navigation view?
I do exactly this in my app. Within AppDelegate I have this code:
#implementation UINavigationBar (CustomImage)
- (void)drawRect:(CGRect)rect
{
UIImage *image = [UIImage imageNamed: #"custom_nav_bar.png"];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
#end
I modified Mike Rundle's version so that the a custom image can be set if necessary. I also merged in 40lb-suit-of-bees suggested changes. initImageDictionary needs to be called during initialisation:
//UINavigationBar+CustomImage.h
#import <Foundation/Foundation.h>
#interface UINavigationBar(CustomImage)
+ (void) initImageDictionary;
- (void) drawRect:(CGRect)rect;
- (void) setImage:(UIImage*)image;
#end
//UINavigationBar+CustomImage.m
#import "UINavigationBar+CustomImage.h"
//Global dictionary for recording background image
static NSMutableDictionary *navigationBarImages = NULL;
#implementation UINavigationBar(CustomImage)
//Overrider to draw a custom image
+ (void)initImageDictionary
{
if(navigationBarImages==NULL){
navigationBarImages=[[NSMutableDictionary alloc] init];
}
}
- (void)drawRect:(CGRect)rect
{
NSString *imageName=[navigationBarImages objectForKey:[NSValue valueWithNonretainedObject: self]];
if (imageName==nil) {
imageName=#"header_bg.png";
}
UIImage *image = [UIImage imageNamed: imageName];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
//Allow the setting of an image for the navigation bar
- (void)setImage:(UIImage*)image
{
[navigationBarImages setObject:image forKey:[NSValue valueWithNonretainedObject: self]];
}
#end
Mike Rundle and Casebash's code is great. I used [NSValue valueWithNonretainedObject:self] to avoid the copyWithZone error. Wrapping self in an NSValue object allows it to be copied into the navigationBarImages dictionary.
- (void)drawRect:(CGRect)rect
{
NSString *imageName=[navigationBarImages objectForKey:[NSValue valueWithNonretainedObject:self]];
...}
- (void)setImage:(NSString*)image
{
[navigationBarImages setObject:image forKey:[NSValue valueWithNonretainedObject:self]];
}
http://foobarpig.com/iphone/uinavigationbar-with-solid-color-or-image-background.html
Hope it helps..
You can use this also
if([self.navigationController.navigationBar respondsToSelector:#selector(setBackgroundImage:forBarMetrics:)] ) {
//iOS 5 new UINavigationBar custom background
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:#"navbg_ForiPhone5_Imagename.png"] forBarMetrics: UIBarMetricsDefault];
} else {
[self.navigationController.navigationBar insertSubview:[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"navbg_ForOtherIphone_Imagename.png"]] atIndex:0];
}
`
http://developer.apple.com/iphone/library/featuredarticles/ViewControllerPGforiPhoneOS/UsingNavigationControllers/UsingNavigationControllers.html#//apple_ref/doc/uid/TP40007457-CH7
Looking at Figure 1 in that link - would it be better to set the backgroundImage on your navigationbar not your navigationitem?
UIImage *image = [UIImage imageNamed: #"navigator.png"];
[_homeNavigationController.navigationBar setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];
Unfortunately, there is no support for using custom background images in a navigation bar in iPhone OS 3.0 or any previous versions. The only way to customize the appearance is to set the style and tint color. Not perfect, I know.
In your code you are trying to stretch the title view of the navigation bar to "go under" the right button. But this is impossible since the three views of a navigation bar (back button, title, and right button) are supposed to be in the same layer and are adjusted to not overlap. This is a feature.
I know there are a number of third-party apps that change the background image but they are "hacking" the system and are using unsupported private API:s or assumptions of the internal data structures of the navigation bar. These programs will most likely fail (crash or display incorrectly) in future versions of iPhone OS.
You most likely don't want to mess with this. Accept the fact that that you cannot (yet) have a custom background image in navigation bars. It hurts, I know. But if you hack the system and your app fails in a future versions of the OS, Apple will pull the app from the app store and you will lose all revenue until you have changed the app. It's your call...
Related
My app has several viewControllers and for some of them, I would like to use a different navigationbar background image when they are pushed onto the navigation stack.
For example, when my mainViewController loads up, I have this:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSLog(#"Setting toolbar for iOS 5+");
UIImage * navbarImage = [UIImage imageNamed:#"navbar01.png"];
[[UINavigationBar appearance] setBackgroundImage:navbarImage forBarMetrics:UIBarMetricsDefault];
}
Likewise, when my other viewController is pushed onto the navigation stack, I am using the same code as above, except using a different UIImage (navbar02.png).
However, the navigation bar doesn't change from the first image that I set. Is there any way to change the UINavigationBar background image when a new view appears?
Thank you!
Here is the link for similar question: UINavigationBar setBackgroundImage: forBarMetrics: Not Working
The answer is to use this:
[self.navigationController.navigationBar setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];
rather than the code you have used.
float version = [[[UIDevice currentDevice] systemVersion] floatValue];
// NSLog(#"%f",version);
if (version >= 5.0) {
UIImage *backgroundImage = [UIImage imageNamed:#"image.png"];
[self.navigationController.navigationBar setBackgroundImage:backgroundImage forBarMetrics:UIBarMetricsDefault];
}
else
{
// UIImage *backgroundImage = [UIImage imageNamed:#"image.png"];
NSString *barBgPath = [[NSBundle mainBundle] pathForResource:#"NavBar" ofType:#"png"];
[self.navigationController.navigationBar.layer setContents:(id)[UIImage imageWithContentsOfFile: barBgPath].CGImage];
}
its working successfully for me ... maybe it will help you.
I've been trying to change the background image of the UINavigationBar of my application. I tried several ways. First I added to my AppDelegate class the following code:
#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
But it wasn't working. My next try was to write a CustomizedNavigationBar Class which is overriding the drawRect method. It looked like that:
CustomizedNavigationBar.h
#import <UIKit/UIKit.h>
#interface CustomizedNavigationBar : UINavigationBar
#end
CustomizedNavigationBar.m
#import "CustomizedNavigationBar.h"
#implementation CustomizedNavigationBar
- (void) drawRect:(CGRect)rect {
UIImage *image = [UIImage imageNamed: #"navigationbar.png"];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
NSLog(#"I got called!!!!!");
}
#end
In my .xib file where the NavigationBar is defined I changed the class to the new CustomizedNavigationBar. But still it is not working..
As another test I downloaded an example project where the background image should be changed. But even with that sample code it was not working.
What am I doing wrong? I am using IOS 5. Any suggestions or other ways I could define a background image?
Thanks for your answers!
Starting in iOS 5 you should use the -setBackgroundImage:forBarMetrics: method:
[myNavbar setBackgroundImage:[UIImage imageNamed: #"UINavigationBarBackground.png"]
forBarMetrics:UIBarMetricsDefault];
And in Swift 4:
navigationBar.setBackgroundImage(UIImage(named: "UINavigationBarBackground.png"),
for: .default)
Considering all iOS versions, this seems to be accomplishing both Custom background image and Custom size of UINavigationBar:
#interface CustomNavigationBar : UINavigationBar
#end
#implementation CustomNavigationBar
-(void) drawRect:(CGRect)rect
{
UIImage *image = [UIImage imageNamed: #"navigationBar"];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
//for iOS5
[self setBackgroundImage:[UIImage imageNamed: #"navigationBar"] forBarMetrics:UIBarMetricsDefault];
}
//for custom size of the UINavigationBar
- (CGSize)sizeThatFits:(CGSize)size {
CGSize newSize = CGSizeMake(320,31);
return newSize;
}
#end
I use such codes in a common place like a Utilities file.
Hope this helps.
Just try with this code.. In your implmentation (.m) file.
#import "RootViewController.h"
#implementation UINavigationBar (CustomImage)
- (void)drawRect:(CGRect)rect {
UIImage *image = [UIImage imageNamed: #"navheader.png"];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
#end
#implementation RootViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
self.title=#"You are Done.";
}
This has worked in excellent way for me.
Above Code Worked for only IOS 4. if you use the IOS 5 then use.....
[myNavbar setBackgroundImage:[UIImage imageNamed:
#"UINavigationBarBackground.png"]
forBarMetrics:UIBarMetricsDefault];
You can add UIImageview to navigation bar as follows
UINavigationBar navBar = [[UINavigationBar alloc]init];
[navBar addSubview: imageview];
[navBar release];
You can check the post :
iPhone - NavigationBar Custom Background
You can also try this for Navigationbar Background.
UINavigationBar *navigationBar = self.navigationController.navigationBar;
UIImage *image = [UIImage imageNamed: #"NavBar-Wood.png"];
[navigationBar setBackgroundImage:image forBarMetrics: UIBarMetricsDefault];
self.navigationController.navigationBar.tintColor = [UIColor brownColor];
Thanks.
Another way to set an image in navigation bar is,
UIImage* logo = [ UIImage imageNamed:#"Logo.png" ];
UIImageView* logoView = [[[UIImageView alloc] initWithImage:logo] autorelease];
self.navigationItem.titleView = logoView;
This will not change whole navigation bar background. But adds a background image centered on the navigation bar, which is sometime more intended (what I was looking for).
Well for iOS 4 there is a simple solution, like:
nvc.navigationBar.layer.contents = (id)img.CGImage;
I would like to set an image background to the navigation bar on my iphone app. Most solutions suggest using drawRect in a category like:
#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, Apple does not recommend this. Any other suggestion?
Thx for helping,
Stephane
Apple strongly advise us to use subclasses rather than categories (WWDC 2011, Session 123).
Create a subclass which implements the drawRect: method and set the class of your navigation bar to your custom class:
if you're working in Interface Builder, change the class in the inspector
if you create a stand-alone navigation bar (without nav controller), instantiate your custom class
if you create a navigation controller programmatically, you could take advantage of the ObjC runtime.
Class switch at runtime:
#import <objc/runtime.h>
...
object_setClass(theNavController.navigationBar, [CustomNavigationBar class]);
You should also avoid using [UIImage imageNamed:...] each time in drawRect: as it might have an impact on performance (for animations). Cache it in an ivar:
if (!bgImage) {
bgImage = [[UIImage imageNamed:#"NavigationBar.png"] retain];
}
[bgImage drawInRect:...];
(and release it in dealloc)
Note: As iOS 5 is still under NDA, I can't mention how you could easily add a background image. Check out the docs for UINavigationBar.
Tested Code : 100 % works
in ur ViewDidLoad
UIImageView *iv=[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"urNavBarImage.png"]];
self.navigationItem.titleView = iv;
[iv release];
NOTE:urNavBarImage should be exact size of Navigation Bar. Like this u can change every Viewcontroller Navigation bar.
I have created a custom category for UINavigationBar as follows
UINavigationBar+CustomImage.h
#import <UIKit/UIKit.h>
#interface UINavigationBar (CustomImage)
- (void) setBackgroundImage:(UIImage*)image;
- (void) clearBackgroundImage;
- (void) removeIfImage:(id)sender;
#end
UINavigationBar+CustomImage.m
#import "UINavigationBar+CustomImage.h"
#implementation UINavigationBar (CustomImage)
- (void) setBackgroundImage:(UIImage*)image {
if (image == NULL) return;
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
imageView.frame = CGRectMake(110,5,100,30);
[self addSubview:imageView];
[imageView release];
}
- (void) clearBackgroundImage {
NSArray *subviews = [self subviews];
for (int i=0; i<[subviews count]; i++) {
if ([[subviews objectAtIndex:i] isMemberOfClass:[UIImageView class]]) {
[[subviews objectAtIndex:i] removeFromSuperview];
}
}
}
#end
I invoke it from my UINavigationController
[[navController navigationBar] performSelectorInBackground:#selector(setBackgroundImage:) withObject:image];
So I've been researching on how to have an image in UINavigationBar and the safest way to do it that works for iOS 4 and iOS 5 is via subclassing the UINavigationBar, so I had:
#interface CustomNavigationBar : UINavigationBar
#end
#implementation CustomNavigationBar
-(void) drawRect:(CGRect)rect
{
UIImage *image = [UIImage imageNamed: #"myNavBarImage"];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
#end
Now say I wanted to hook up ProfileViewController to have this custom UINavigationBar, how do I do that? Here's how I set ProfileViewController.
ProfileViewController *profile = [[ProfileViewController alloc] init];
localNavigationController = [[UINavigationController alloc] initWithRootViewController:profile];
[localControllersArray addObject:localNavigationController];
[localNavigationController release];
[profile release];
Any idea on how to wire this up? I've read that this has to be done via IB by changing the class of my UINavigationBar to the class that I just created. However, I don't have any UINavigationBar in my xib file, as it is created programatically via the UINavigationController.
One other issue also is that if I wanted to have a dynamic image that I can change/specify to the UINavigationBar, how do I do this? As of now it is hard wired that the UINavigationbar will have an image called myNavBarImage, but what if I wanted to set it to something else so I don't have to create 10 custom UINavigationBar, I somehow wanted to set the image name.
There is a solution similar to yours but uses categories instead of subclassing:
http://www.developers-life.com/custom-uinavigationbar-with-image-and-back-button.html
However, you have other choices that will make it easier for you such as adding an image as a subview to UINavigationBar. It is a safe way to do it,and I used it in a previous project which was approved.
My favorite way to do it is hiding the navigation bar and adding an imageView with buttons to have full control on how the navigation bar looks like (I especially use it when I need to add custom buttons as well).
Edit (Code to use for the second issue):
At viewDidLoad
UIImageView *imageview = [[UIImageView alloc] initWithImage: [UIImage imageNamed: #"image1.png"]];
[self.navigationController.navigationBar addSubview:imageview];
[self.navigationController.navigationBar sendSubviewToBack:imageview];
[imageview release];
At the method that changes the image:
-(void) changeNavigationBarImage: (NSString *) imageName{
for (UIView *view in self.navigationController.navigationBar.subviews) {
if ([view isKindOfClass:[UIImageView class]])
{
[(UIImageView *)view setImage:[UIImage imageNamed:imageName]];
break;
}
}
}
You can call this method when you want to change the image (i.e. button or timer)
I want to be able to make custom buttons which have an image background using a scale9 type background image meaning the width of the button can be dynamic. I have seen example on the web of people doing this on a per button basis but it seems to me that wouldn't it be better to create a new object which subclasses UIButton which you can then use in Interface Designer as the class for any custom button (round rect button set to custom).
Here is what I have so far.
#import <Foundation/Foundation.h>
#interface LargeButton : UIButton {
}
#end
#import "LargeButton.h"
#implementation LargeButton
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.frame = CGRectMake(0, 0, 170.0, 48.0);
// Center the text vertically and horizontally
self.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
self.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
UIImage *image = [UIImage imageNamed:#"btnBigPurple.png"];
// Make a stretchable image from the original image
UIImage *stretchImage =
[image stretchableImageWithLeftCapWidth:15.0 topCapHeight:0.0];
// Set the background to the stretchable image
[self setBackgroundImage:image forState:UIControlStateNormal];
// Make the background color clear
//self.backgroundColor = [UIColor clearColor];
}
return self;
}
#end
This doesn't however seems to work. When I run this im simulator I see the button text but the button has no background. I have placed a breakpoint and I know its running and check the console and have no errors.
Can someone help? fix this or is my way of thinking wrong?
Thanks
I fixed it myself. For those who are interested.
#import <Foundation/Foundation.h>
#interface LargeButton : UIButton {
}
#end
#import "LargeButton.h"
#implementation LargeButton
- (void)drawRect:(CGRect)rect{
UIImage *greenBalloon = [[UIImage imageNamed:#"btnBigPurple.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:0];
[self setBackgroundImage:greenBalloon forState:UIControlStateNormal];
}
#end
Simple but effective.