ABPeoplePickerNavigationController "Groups" View Navigation Controller - iphone

I'm using a custom Navigation Bar appearance in my app with this code in the App Delegate's application:didFinishLaunchingWithOptions: method:
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:#"navBar.png"] forBarMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setBackgroundColor:[UIColor clearColor]];
However, this appearance breaks when I present an ABPeoplePickerNavigationController (to allow selection of a contact to populate the To: field for a new email), because the system uses an extra tall UINavigationBar when this view is showing due to the prompt property on UINavigationItem being set by the system ("Choose a contact to mail").
The fix is to add this code:
[[UINavigationBar appearanceWhenContainedIn:[ABPeoplePickerNavigationController class], nil] setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
[[UINavigationBar appearanceWhenContainedIn:[ABPeoplePickerNavigationController class], nil] setBarStyle:UIBarStyleBlack];
Which looks like this:
However, this little hack doesn't work when you tap the Groups button from the initial view. It still looks broken due to the extra tall Navigation Bar:
Any ideas what the controller name is for that view (so I can apply the same exclusion as above), or another way to fix this?

I'm just hitting this now.. any luck resolving? I'm thinking to try interating through the ABPeoplepickerNavigationControllers view controllers and applying appearanceWhenContainedIn method...

I've been fighting with this as well, but think I've pieced together a solution.
The group selection view is some other (unknown to me, likely private) class, so we can't specify an exception style through an appearance-proxy-when-contained-in approach, as you've done for the ABPeoplePickerNavigationController. Instead, we should try and resolve the original issue, which is the custom background image not rendering properly when the prompt is shown and the navigation bar is tall.
The solution here (iOS5 UINavigationBar background image issues when prompt is shown) suggests using a resizable background image for the navigation bar.
That almost worked for me, but the background image I was using included the shadow for underneath the navigation bar and that wasn't resizing correctly when the prompt was shown. Instead, I had to use a resizable background image without a shadow and then specify the shadow image separately.
UINavigationBar* navigationBar = [UINavigationBar appearance];
[navigationBar setBackgroundImage:[[UIImage imageNamed:#"TopBarBackgroundNoShadow"] resizableImageWithCapInsets:UIEdgeInsetsMake(3, 0, 3, 0)]
forBarMetrics:UIBarMetricsDefault];
[navigationBar setShadowImage:[UIImage imageNamed:#"TopBarShadowResize"]];
Using this approach removed the need for any exception styling and looked good in both the ABPeoplePickerNavigationController and the group selection view, as well as at standard height.

Related

UINavigationBar handle rotation

I'm trying to handle the rotation of a UINavigationBar with UINavigationItem (i'm not using the UINavigationController), i have successfully made so that the height and width show according, but that does not seems to be correct, as the UINavigationBar still acts as being in portrait mode (big title and button), also when i set a custom background for both metrics, it seems to only show the portrait background metric, ignoring completely the landscape one.
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:#"modal-top-landscape"] forBarMetrics:UIBarMetricsLandscapePhone];
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:#"modal-top"] forBarMetrics:UIBarMetricsDefault];
Is there a way to tell the UINavigationBar that is rotated and should show the text and buttons accordingly?
I attach some screenshots:
One workaround for this is to use a UINavigationController, and use a CGRectOffset to remove the margin that leaves the status bar... add the Controller to the parent controller (also the view).

iOS5 Toolbar background image

I'm very new to iOS programming.
I'm trying to set the toolbar background to a custom image.
I'm also using storyboards.
How do I go about that?
Do I edit UIToolbar in the UI Kit framework? Do I need to change something in Storyboard?
Thanks,
You can use UIToolbar's built-in -setBackgroundImage:forToolbarPosition:barMetrics: method:
// portrait
[yourToolbar setBackgroundImage:[UIImage imageNamed:#"YourToolbarBkg-Portrait.png"] forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
// landscape
[yourToolbar setBackgroundImage:[UIImage imageNamed:#"YourToolbarBkg-Landscape.png"] forToolbarPosition:UIToolbarPositionAny barMetrics: UIBarMetricsLandscapePhone];
YourToolbarBkg-Portrait.png will be 320x44 bkg image for portrait mode
YourToolbarBkg-Landscape.png will be 480x32 bkg image for landscape mode.
UIToolbar inherits from UIView. This just worked for me:
[topBar insertSubview:[[[UIImageView alloc] initWithImage:[UIImage imageNamed:BAR_BKG_IMG]] autorelease] atIndex:0];
UPDATED
topBar ------ is the outlet of the UIToolBar u are using
use this code where u are creating ur UIToolBar the class which implements the UIToolbar..
plus tell me y r u using Toolbar whats ur main purpose for it
Instead of editing UIToolBar, why not create a UIView of the same size and skin that however you would like? That would be easier if you are new.
Or if you want to override UIToolbar:
#implementation UIToolbar (CustomImage)
- (void)drawRect:(CGRect)rect {
UIImage *image = [UIImage imageNamed: #"image.png"];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
#end
Had a right faff with background images for ToolBars and NavBars. I know setting the background image of a NavBar and ToolBar is generally a doddle. But, when you're presenting modal VC's, for some insane reason, where a NavBar is being added and you DO change the background image, it appears to double in size. Altering the height has strange results.
My issue was where I was using a NavController all over my App, but needed a modal view for one or two aspects of it. Simple enough. However, I needed either a NavBar or ToolBar type header with a Done button to pop the VC off the stack. Again, not an issue. But I needed the NavBar or ToolBar to look the same as everywhere else in my App.
I settled on a ToolBar, seeing as the VC was being presented modally. So, there my ToolBar sat, in typical Apple-blue. Nice, but not how the rest of my App looked, where a blackened image was being used for each NavBar. Using the iOS 5 appearance proxy, I altered the background image of the ToolBar. And this worked. But, unless I had the UIImage in exactly the proportions and size expected by the Tool Bar, I was in a pickle. The image simply did not look right at all. So, I decided to create a UIIMageView, where I could control the content mode, then insert a subview onto the toolBar.
Take a look at my code below.
UIImageView *toolbarImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:NAV_BAR_BACKGROUND]];
[toolbarImageView setFrame:[self.IBOToolBar bounds]];
[toolbarImageView setContentMode:UIViewContentModeScaleAspectFill];
[self.IBOToolBar insertSubview:toolbarImageView atIndex:1];
It's a bit of a fluff but I do hope this helps someone alter the image on their ToolBar.
NAV_BAR_BACKGROUND can be defined as follows:
#define NAV_BAR_BACKGROUND #"navBarBlackMattDarkSquare.png"

How do you target particular UIViews when styling its UIAppearance?

I am setting global styles in iOS 5 with UIAppearance. Here's an example:
[[UIbarButtonItem appearance]
setTtitletextAttributes:someStyle
forState:UIControlStateNormal
];
It looks good in most cases:
But there are cases where the global style looks ugly, like in a movie player.
For the movie player, I would prefer to have the default blue button. So how would I target only the back button's appearance and not the done button's appearance? I have similar issues with targeting normal table cells and grouped table cells.
You need to use a custom subclass of UINavigationBar. Let's call it MyNavigationBar. Then you can do this:
[[UIBarButtonItem appearanceWhenContainedIn:[MyNavigationBar class], nil]
setTintColor:[UIColor redColor]];
and it will only affect buttons within your navigation bar, not the MPMoviePlayerController's navigation bar.
The problem, of course, is that UINavigationController always uses a basic UINavigationBar... if you create it in code. But if you create it in a nib, you can click on its navigation bar (in the nib's document outline) and change the bar's class in the Identity inspector.
If in your AppDelegate you just replace
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:#"navback"]
forBarMetrics:UIBarMetricsDefault];
with
[[UINavigationBar appearanceWhenContainedIn:[UINavigationController class], nil]
setBackgroundImage:[UIImage imageNamed:#"navback"] forBarMetrics:UIBarMetricsDefault];
movie player will have proper black bar in full screen mode. Works in iOS 5 and iOS 6
You can actually change the proxy to just target certain view hierarchies. In other words, when the view you want to customize is contained in a certain view, you can modify its appearance differently from the rest. So set your global (white) style first, but then call the following method to customize the appearance for when the button appears in an MPMoviePlayerController or whatever else.
[[UIBarButtonItem appearanceWhenContainedIn:
[MPMoviePlayerController class], nil]
setTitletextAttributes:someStyle
forState:UIControlStateNormal];
Let me know if that helps!

setting UINavigationBar tintColor only sets it's back button color

SO I am setting a UINavigationBar tintColor and here's what I get:
[navController.navigationBar setTintColor:[UIColor whiteColor]];
How is this even possible? Here's some more info if it helps:
I've got a UINavigationController that I customize as follows:
First, come up with a 44px-high image as the background for the nav bar. (In this case, if you wanted to use a 44px-high white image, that'd do the trick --- but it'll look much nicer if you use some type of vertical gradient)
Second, use the following code in your AppDelegate's didFinishLaunching method. (The image is called "background_44.png".
// Set the background image for *all* UINavigationBars
UIImage *gradientImage44 = [[UIImage imageNamed:#"background_44.png"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
// Set the background image for *all* UINavigationBars
[[UINavigationBar appearance] setBackgroundImage:gradientImage44
forBarMetrics:UIBarMetricsDefault];
I dropped that code in my project, worked fine. Even changed bar styles and colors. No problem. This line of code is fine, there is an issue somewhere else or its some crazy glitch.

Alter a UIBarButtonItem view to be transparent programmatically

I've had trouble getting this to work, nowhere have I seen a working example on the web. Now offering bounty on this as its making me crazy. It should be easy, but that doesn't seem to be the case.
I'd like my buttons on my UINavigationBar to be semi-transparent such that they allow the background of whatever is on the UINavigationBar to show through. This effect is seen in many applications, image examples below. You can do this by setting a custom background on the item, which i think is an unacceptable solution because it requires that you prepare images beforehand, and they won't be adaptable for variable buttons etc. They will not look like Apple UI and I don't believe there is a reason to do this either, UIKit is already drawing the background for these buttons, we just need to change it. The correct solution uses the bar items and views generated by Apple's apis.
UIBarButtonItem is not a UIView subclass. When you create one and add it to a UINavigationBar, some code somewhere in the framework draws a view for it. The framework methods seem to resist anything related to allowing transparency of the bar items, such as the tintColor property.
For example, this does NOT work:
UINavigationItem *item = [[UINavigationItem alloc] init];
UIBarButtonItem *editButton = [[UIBarButtonItem alloc] initWithTitle:#"SUCKS" style:UIBarButtonItemStyleBordered target:self action:#selector(whatever:)];
editButton.tintColor = [UIColor colorWithWhite:0.4 alpha:0.3];
item.leftBarButtonItem = editButton;
Nothing I do will make UINavigationBar allow semi-transparency for its bar items. I believe at runtime we need to:
Get the image for the bar item
Mask it for transparency
Set the new image on the bar item
But I haven't been able to get the image at runtime or mask it properly. How do you do this?
Create a custom uiview and draw a semi-transparent black rectangle in it and use that view with initWithCustomView.
see
and
Failing that, you may have to use an image (png). e.g. a 1x1 black pixel png with 30% opacity.You could then initWithImage.
EDIT: I have had this second approach working using:
buttonThree = [[UIBarButtonItem alloc] initWithTitle:#" sort button " style:UIBarButtonItemStyleBordered target:self action:#selector(sortMethod)];
UIImage *thebgUIimage = [UIImage imageNamed:#"semi.png"];
[buttonThree setBackgroundImage:thebgUIimage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
This results in a button that has a transparent background image that the navbar background image shows through. However, you would need to create an image with the rounded corners on and so need an image for each button width. Also I found this thread after trying the above
A brilliant hack is to use the UISegmentedControl with a single segment (as a button) and set its tint color. Have a look at http://charles.lescampeurs.org/2011/02/10/tint-color-uibutton-and-uibarbuttonitem. I have personally implemented this. Feel free to ask any questions.
Instead of searching for code and breaking your head, my suggestion is just to have transparent image which has just border similar to button (add shadow if necessary), create a button of custom type, add the transparent background image to it and you can text as you want. From this custom button, create your bar button item accordingly.
If you're targeting for iOS 5, you can set the background image of the button.
[_button setBackgroundImage:#"image" forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
Note that you'll need to set background images for state UIControlSateSelected and again for both control states for barMetrics: UIBarMetricsLandscape, if your application allows landscape orientation.
Note again this is an iOS 5 feature.
I believe your answer is here: http://sebastiancelis.com/2009/12/21/adding-background-image-uinavigationbar/