Clear iPhone Navigation Bar Image - iphone

I am currently using this code in my App Delegate to set a custom background image for the Navigation bar:
#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
It works great, and for all the views in my App I set the Navigation bar title to show no text (so it won't cover up the background image).
One of the views presents a modal view controller (an EKEventEditViewController to be exact), and the title in the Navigation bar says "Add Event", which shows up on top of my custom image.
I have tried several ways to change the title (to no avail), but would rather prevent the custom Navigation bar background image from showing up only in this modal view.
Does anyone know of a way to do this while still using the stated method for setting the Navigation bar background image?

please, never ever do this...
You are replacing the drawRect: method in UINavigationBar, very brittle and likely to cause you (and your users) headaches.
Your background will always show up in all instances of UINavigationBar because you have replaced the implementation of drawRect:
There is no way to replace the title of the EKEventEditViewController. Of course there is always a way, but its even worse than replacing the implementation of drawRect:
Instead, please make a subclass of UINavigationBar and use that in the places you require a custom nav bar.

Related

How to make a view have a semi-transparent border and show the view below

Probably a bit of a newbie question, but .... I am writing an iPhone app which uses UITabBarController.
In Interface Builder I've setup the tab bar in MainWindow.xib. I have 4 tabs, and each one is set to load the xib for the appropriate UIViewController subclass. I have created the views in the xib files for each UIViewController subclass in Interface Builder.
All is working well in that I can tap each tab and it shows the view for the correct UIViewController
But what I really want is for the view for one of the UIViewController subclasses to have a semi-transparent border of approx 30px on all 4 edges, so that it shows the edges of the view behind, kind of greyed out.
IE. the first tab is the main application, and that takes up the whole screen (minus the status and tab bar areas).Tab 2 is to save, and I want it to look like a small modal window over the top of the main app.
(If I were doing this as a html web app, the terminology and technology I'd be using would be a jQuery overlay)
Does this make sense?
I've tried playing with presentModalViewController but this makes it worse in that it takes up the entire screen including the status and tab bar areas.
Any help or pointers very much appreciated
Cheers
Nathan
Your UIViewController cannot be transparent to the view below it because the iphone may unload the view below it that is not currently being shown (to save memory).
The best solution I have used is to take a picture of the current view before you push your new view controller and then use that as the background image (fake the transparency). Here's how I implemented this:
NewViewController *newView = [[NewViewController alloc] init];
shareVC.imageBackground = [Utilities getScreenshot:self.view];
[self presentModalViewController:newView animated:YES];
[newView release];
then on your newViewController do this (on viewDidLoad, viewWillAppear, etc):
[imageView setImage:imageBackground];
and here's the screenshot function
+(UIImage *)getScreenshot:(UIView *)_view {
//take a screenshow of the parent view so we can add it as a background to the modal view
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)])
UIGraphicsBeginImageContextWithOptions(_view.window.bounds.size, NO, [UIScreen mainScreen].scale);
else
UIGraphicsBeginImageContext(_view.window.bounds.size);
[_view.window.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
You then need to setup your new view with a UIImageView as the background and pick the right Alpha value for that imageView to make it appear like it's transparent.

Mailcomposer with custom Navigationbar

i am facing a new problem.
I have custom navigation controller in my application. I have to add an image to navigationbar and i used this code in my AppDelegate-
#implementation UINavigationBar (CustomImage)
- (void)drawRect:(CGRect)rect {
UIImage *image = [UIImage imageNamed: #"top-red.png"];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, 44)];
}
#end.
This code is working fine for me, but when i use MFMailComposer in my application and call it on a button event i see that the navigationbar of MFMailcomposer is also changed to my custom navigationbar which i don't want to change.
Any Ideas!!!
By adding a category to the UINavigationBar, you are adding a method to all instances of UINavigationBar.
Since you are overriding drawRect: that means that whenever any navigation bar wants to draw itself it is using your method rather than the standard drawRect:
Rather than do this, you should just add the image to your navigation bars where you want them , rather than change it globally as you have done here.

Can we put a static image banner image at the top of every screen?

Our customer decided their application did not have enough branding in it, and they want to put their logo in a banner at the top of every screen. The logo banner is about the same height as the navigation bar header, and can just be a static image.
Our app has many different screens, including many driven by a UINavigationController. We cannot put the logo into the "title" portion of the nav controller, because then we do not get to display the title for that view.
Looking at iOS apps, it's clear that this is not common. Has anyone had to do this before, and how did you accomplish it?
Thanks for any tips!
This is not an ideal approach, honestly, because as you mentioned, it isn't very common. Indeed, Apple might not accept apps that displace things such as the navigation bar.
In any case, if you must do this, you can add some sort of banner view directly to your window in the app delegate. After this, you must have sure to set the frame of the window's root view controller to be below the visible portion of the banner ad. From here, the rest of the views will be contained within the frame you specify, which is normally the size of the screen.
You can add the logo to your application's MainWindow and set transparency to all the viewControllers backgrounds. But note that this means that all your viewControllers will share the same background (the one from MainWindow).
You can do this - look at the XFactor UK app for an example ( http://itunes.apple.com/gb/app/the-x-factor-uk/id455682741?mt=8 ) - the navigation bar is branded throughout the app.
The bad news is it's pretty hard to do - we ended up applying a category to UINavigationBar to override drawRect and putting the background in there e.g.:
#implementation UINavigationBar (extras)
- (void)drawRect:(CGRect)rect {
UIImage *image;
if (self.frame.size.width>320) {
image = [UIImage imageNamed: #"NavigationBarWide.png"];
} else {
image = [UIImage imageNamed: #"NavigationBar.png"];
}
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
You can keep the banner logo in AppDelegate file and set the frame for BannerLogo. This would be same as displaying ads with iAds or AdMobs. I have done this to display AdMob on all the screen. You need to add BannerLogo as a subView to display on all views.

iOS: Adding a fixed image just below the navigation bar

It feels like this should be fairly simple but nothing i've tried so far has worked. In a nutshell, I want to add a fixed image just below the navigation bar in a UITableViewController that i create programmatically. In other words, I want the image to stay just below the navigation bar even as the user scrolls up and down the table view (it's basically a custom drop-shadow for the navigation bar).
The closest I've gotten is the code below (in the UITableViewController's init method), which adds the image but doesn't keep it from moving when the user scrolls.
// Add nav bar drop shadow
UIImage *dropShadowImage = [UIImage imageNamed:#"NavBarDropShadow.png"];
UIImageView *dropShadowView = [[UIImageView alloc] initWithImage:dropShadowImage];
[self.view addSubview:dropShadowView];
Is there an easy way to add an add an image to the screen programmatically, position it wherever you like, and have it stay there even as the user scrolls? Thanks for any and all input!
EDIT: IOS5 has a better way to do this. Please check out the new UIAppearance protocol.
Adding this block of code to your code will allow you to draw your shadow on all UINavigationBars in the app. This is a better solution than adding the shadow as a UIImageView:
#implementation UINavigationBar (ShadowBar)
- (void)drawRect:(CGRect)rect {
//draw the shadow ui nav bar
UIImage *image = [UIImage imageNamed: #"UINavBarWithShadow.png"];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
- (void)layoutSubviews {
self.frame = CGRectMake(0, 0, self.frame.size.width, 300);
}
#end
To make the UINavigationBar higher and thus not clipping your content, override the layoutSubviews and set the frame you need (the code above assumes your header is 300 points high). layoutSubviews does nothing by default, but is "lazy" called before lay-outing the view.
For more info about this custom size/look overrides that apply to UIView (and any other subclass) have a look here
You can make a subclass or a category on UINavigationBar, and have it add the image in the init or drawRect methods. If you think about it, you're trying to add a shadow to the navigation bar, not to the UITableView, so it makes sense to modify the navbar, not the table.
You are adding your dropShadowView to self.view that in your case is the view of an UITableViewController. It means that your self.view is an UITableView so when you scroll up and down you scroll the dropShadowView as well because is inside the tableView.
Try to write a custom UIViewController and add two subviews: one is the dropShadowView and the other one is your table.
Have a look at this similar question I answered a while back. It should do exactly what you want with little customization.
Transparent View at the Top of a UITableView
Dont make a UITableView the main view ie. the view outlet, set that to a UIView that contains a UITableView, then make your controller a subclass of UIViewController, and make it conform to UITableViewDataSource and UITableViewDelegate. in your nib, set up your view so that you have a UIImageView at the top and a UITableView below. and set the delegate and datasource to your file's owner.

How would I draw a line at the bottom of a UINavigationBar?

The design I've been given for an iPhone app I'm working on calls for a 1px red line at the bottom of the navigation bar. I know how to draw a line with Quartz and -drawRect, but how do I get access to the UINavigationBar's view? Or would it work to draw the line in the app's main view, on top of everything else?
Duncan Wilcox's answer below works to get the line drawn, but then buttons on the bar become impossible to press.
If I do [self.navigationItem.titleView.superview sendSubviewToBack:titleView] then buttons that are created in nib files work, but not ones that are dynamically added.
I guess the answer depends on where you want the red line, as part of the navigation bar or just under it. That would be only 1 pixel difference, but designers are demanding these days :)
If you want it below the navigation bar you definitely have to put it in all of the app's views where the line is needed.
There's a surprisingly simple way to alter the look of the navigation bar, I used it for skinning the entire navbar look but it will probably work for even only some parts of the navbar if you make the image partially transparent.
Basically we want to skin the UINavigationItem of a UIViewController that's in your navigation hierarchy.
create a 320x44 image containing your custom navbar look
add a UIImageView to the XIB where the UINavigationItem is
link the titleView property of the UINavigationItem to the UIImageView
This almost works, except that the title view will be resized in wierd ways. To fix that I have a UIImageView subclass that keeps the image properly set:
#implementation TitleViewHack
- (void)setFrame:(CGRect)frame
{
frame.size.width = 320;
if(frame.origin.x > 0 && frame.origin.x < 20)
frame.origin.x = 0;
[super setFrame:frame];
}
#end
So instead of using a UIImageView above you'll use this TitleViewHack class.
This is what I've settled upon:
// UINavigationBar subclass
- (void)drawRect:(CGRect)rect {
UIImage *image = [UIImage imageNamed: #"background_navbar.png"];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}