How to subclass UINavigationBar to work with Three20/iOS5? - iphone

Many of you have probably noticed that we cant anymore create a category to override UINavigationBar drawRect in iOS5. Now actually I don't see a good way of implementing this customization without using a subclass of UINavigationBar and set it inside a navigationController->navigationBar in my MainWindow.xib. However, TTNavigator do not recognize that navigationController since every TTViewController has their own superclass of TTNavigationController.

I don't know how to solve it for Three20 but in general for supporting IOS 5 you can use this method
UIImage *image = [UIImage imageNamed:#"header.png"];
if([navigationBar respondsToSelector:#selector(setBackgroundImage:forBarMetrics:)] ) {
//iOS 5 new UINavigationBar custom background
[navigationBar setBackgroundImage:image forBarMetrics: UIBarMetricsDefault];
}
else{
UIImageView *imgView = [[[UIImageView alloc] initWithImage:image] autorelease];
[imgView setUserInteractionEnabled:NO];
[imgView setTag:TOOLBAR_TAG];
[navigationBar insertSubview:imgView atIndex:0];
}

Related

Transparent UITabBarController with changeable view in background

I want to have a UITabBarController, which is has an alpha of 0.5, whose transparency allows you to see a view in the background. The background view has to be accesible and changeable.
I'm able to add the background using this technique: https://gist.github.com/1157542
It's a Category which adds a subview to the UITabBarController, and sends the subview to the back. However, because it's a category, I can't make the subview a property. So I can't really access it.
Is there a way to make this background view more flexible and accessible? So I could, for instance, add other subviews to it easily from any of the tab bar controller's view controllers?
Instead of a category, you should subclass UITabBarController. This will allow you to have finer control over the object. Here's an example of a subclass.
// MPCustomTabBar.h
#interface MPCustomTabBar : UITabBarController
- (void) setBackgroundImage:(UIImage *)image;
#end
// MPCustomTabBar.m
#interface MPCustomTabBar
- (void) setBackgroundImage:(UIImage *)image {
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,320,480)];
imageView.backgroundColor = [UIColor colorWithPatternImage:i];
[[self view] addSubview:imageView];
[[self view] sendSubviewToBack:imageView];
[[self view] setOpaque:NO];
[[self view] setBackgroundColor:[UIColor clearColor]];
[imageView release];
}
#end
Now you can do all the customization you want, alloc and init your new subclass by something like this:
MPCustomTabBar *bar = [[MPCustomTabBar alloc] init];
A solution to my problem might be simply this..
In my AppDelegate, just before [self.window makeKeyAndVisible];
self.theImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"image1.png"]];
[self.tabBarController.view insertSubview:self.theImage atIndex:0];
I can then easily change this image, in any of the tab bar controller's view controllers, like:
AppDelegate *appDelegate= (AppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.theImage.image = [UIImage imageNamed:#"image2.png"];
.. no categories required.
Here's what worked for me:
Make TabBar transparent (either by Storyboard or programmatically) by setting the Tint- and Background to Clear Color and Opaque to No.
The black background color is actually the window's colour. Assign the image you want to use as the background to the window itself:
UIImage *i = [UIImage imageNamed:#"main_background.png"];
UIColor *c = [[UIColor alloc] initWithPatternImage:i];
[self.window setBackgroundColor:c];

UIStoryboard application and common background image

I have an iOS application which uses an UIStoryboard to control its flow. I would like to have all my views defined in the UIStoryboard to all share a common background. Is there a way I can do this without having to add an UIImageView control to each View?
I have tried this below but it causes my application crash with a stack overflow error:
-(void)viewDidLoad
{
[super viewDidLoad];
UIImage *image = [UIImage imageNamed:#"MyBackgroundImage.png"];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
[self.view addSubview:imageView];
[self.view sendSubviewToBack:imageView];
}
Is there a better way to do this? What is the best way to handle this kind of theming in iOS applications?
Subclass UIViewController and override -viewDidLoad to create your image and set it as the background of the view. Now make the view controllers that require this background image subclasses of your custom view controller instead of UIViewController.
In your ViewDidLoad:
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 100, 50)];
imgView.image = [UIImage imageNamed:#"image.png"];
[self.view addSubview: imgView];
[self.view sendSubviewToBack:imageView];
Should do the trick.
It turns out that the code I posted above is working perfectly. My solution was the same as Mark Adams' suggestion: Subclass UIViewController, override -viewDidLoad, create and set the imageView, and use the new subclass as my viewController.
I think I may have inadvertently set my new subclass to an incorrect control in Interface Builder which caused my initial solution not to work correctly.

How to wire custom UINavigationBar to UINavigationController

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)

Adding backgroundimage to my app

I am using this code to add a background image to my tableview
myTable.backgroundView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"background.png"]] autorelease];
on the internet they say this code works, but it's not working for me
can someone help me please?
if its a UITableViewController, as I believe it is, do this:
[myTable setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"background.png"]]];
or you can do (on a non-table view controller)
[self.view setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"background.png"]]];
or on viewDidLoad you can do:
UIImageView *backgroundView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"background.png"]] autorelease];
[self.view addSubview:backgroundView];
but thats a bit messy - I prefer to use setBackgroundColor:
The problem is that backgroundview for tableview is a UIView, not a UIImage. So you need to create a view, easiest way is to use a UIImageView. For example this would put your splash screen image as the background view for the table in a UITableViewController...
UIImage *backImage = [UIImage imageNamed:#"default.png"];
UIImageView *backImageView = [[UIImageView alloc] initWithImage:backImage];
self.tableView.backgroundView = backImageView;
The methods mentioned above are pre the introduction of tableview property backgroundview in 3.2
edit - dear god I was obviously having a coffee deficit today :) The op is indeed using a UIImageView! The only thing I can think is that he is targeting a pre 3.2 platform...

how to display an image in the navigation bar of an iPhone application?

how to display an image in the navigation bar of an iPhone application? (say, right after the title)
Here's how to have the image centered in the NavBar.
UIImage *image = [UIImage imageNamed: #"NavBarImage.png"];
UIImageView *imageView = [[UIImageView alloc] initWithImage: image];
self.navigationItem.titleView = imageView;
[imageView release];
This code is actually contained with the Apple source for the NavBar and can be found at the iPhone Developer Center at Apple.
The source shows you various ways to manipulate both the StatusBar & NavBar.
I haven't tested this but as UINavigationBar is a view you can add subViews to it.
UIImage* myImage = [UIImage imageNamed:#"Myimage.png"];
UIImageView* myImageView = [[UIImageView alloc] initWithImage:myImage];
myImageView.frame.origin.x = 30.0; // You will have to find suitable values for the origin
myImageView.frame.origin.y = 5.0;
[myTabbar addSubView:myImageView];
[myImageView release];
You can use things like the backItem property to calculate the position of your image view.
If you want the image at the right of the nav bar, you can define it as a custom button with no action when presed, like this
UIButton* fakeButton = (UIButton *) [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"yourimage.png"]];
UIBarButtonItem *fakeButtonItem = [[UIBarButtonItem alloc] initWithCustomView:fakeButton];
self.navigationItem.rightBarButtonItem = fakeButtonItem;
[fakeButtonItem release];
[fakeButton release];
Simply Place that code in - (void)viewWillAppear:(BOOL)animated; so it'll work fine
and add one image having size 320x40 named Top Bar
UIImage *image = [UIImage imageNamed: #"TopBar.png"];
[self.navigationController.navigationBar setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];
the navigation bar has a property called title view - set this to the image you like. Since the titleView overwrites the title of the nav bar you have to include the desired title in the image file. Still set the title to what you want so it appears on the back button when you push a view Controller
I encountered the same problem.Found out the best solution
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:#"background_image.png"] forBarMetrics:UIBarMetricsDefault];
Hope this would help....
Just write your own navigation bar. Therefore you have to disable the Navigation Bar fist:
Disable the top bar in the interface builder by selecting your Navigation Controller in
your Storyboard: Attributes Inspector -> Simulated Metrics -> Top Bar: select None
Afterwards you can add any HeaderView you like...
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, sFrame.size.width, 100)];
UIColor *background = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"header_image.png"]];
self.headerView.backgroundColor = background;
// ...add buttons and labels
[self.view addSubview:headerView];