UINavigation bar button background image size - objective-c

I'm trying sot set image background for the left back button navigation bar for all the app with this snippet:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
float version = [[[UIDevice currentDevice] systemVersion] floatValue];
if (version >= 5.0)
{
// iPhone 5.0 code here
UIImage *image = [UIImage imageNamed: #"btn_back.png"];
image = [image stretchableImageWithLeftCapWidth:40.0f topCapHeight:0.0f];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:image forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
}
return YES;
}
I've been trying different values in stretchableImageWithLeftCapWidth: but best result was this:
How can I set background image to the correct size?
Thanks

stretchableImageWithLeftCapWidth:topCapHeight: is deprecated. Use resizableImageWithCapInsets: instead.
This should work:
UIImage *buttonImage = [[UIImage imageNamed:#"btn_back.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(1, 10, 1, 10)];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:buttonImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];

Related

Subclass UINavigationbar for customise in iOS7 does not work

I have made a subclass of the navigation bar.
In there I set a background image and I would like to disable the clipping, because my Image has some shadow and an arrow which is higher than the navigation bar.
in iOS 6&5 it works perfectly when I remove the tick Clip Subviews in the Interface Builder in Xcode.
In iOS7 unfortunately the background image is always clipped...
I also tried to add the following lines:
- (void) awakeFromNib
{
// Initialization code
UIImage *image = [UIImage imageNamed:#"tt_navigation_bar.png"];
if ([[UIDevice currentDevice].systemVersion floatValue] >= 7.0) image = [UIImage imageNamed:#"tt_navigation_bar-ios7.png"];
[[UINavigationBar appearance] setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];
NSDictionary *textTitleOptions = [NSDictionary dictionaryWithObjectsAndKeys:[UIFont fontWithName:#"HelveticaNeue-Bold" size:21.0], UITextAttributeFont, [UIColor colorWithRed:255.0/255.0 green:109.0/255.0 blue:36.0/255.0 alpha:1], UITextAttributeTextColor, [UIColor clearColor], UITextAttributeTextShadowColor, nil];
[[UINavigationBar appearance] setTitleTextAttributes:textTitleOptions];
for (UIView *v in [self subviews]) {
NSLog(#"v: %#", v);
v.layer.masksToBounds = NO;
}
self.layer.masksToBounds = NO;
}
I solved this by manually editing my two images into the top n pixels and then "the rest" and setting the image of "the rest" to the shadowImage.

UISegmentedControl setImage: Bug in iOS7

I have a UISegmentedControl in my app. As of iOS7 GM, the images I use are not showing up when run on iOS7 devices. Anyone else having this problem?
Here's what it looks like in iOS6.1 and earlier
.
and here is what it looks like in iOS7
.
Here is the code:
self.theSegmentedControl.frame = CGRectMake(self.theSegmentedControl.frame.origin.x, self.theSegmentedControl.frame.origin.y, 320, 35);
[self.theSegmentedControl setBackgroundImage:[UIImage imageNamed:#"img_toggleInactive"] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[self.theSegmentedControl setImage:[UIImage imageNamed:#"btn_onceActive"] forSegmentAtIndex:0];
[self.theSegmentedControl setImage:[UIImage imageNamed:#"btn_recurringInactive"] forSegmentAtIndex:1];
[self.theSegmentedControl setImage:[UIImage imageNamed:#"btn_scheduledInactive"] forSegmentAtIndex:2];
[self.theSegmentedControl setDividerImage:[UIImage imageNamed:#"separator"] forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
Has anyone found a workaround to this?
Woohoo! Here's the workaround:
//Add clear color to mask any bits of a selection state that the object might show around the images
self.theSegmentedControl.tintColor = [UIColor clearColor];
UIImage *onceActive;
UIImage *recurringActive;
UIImage *scheduledActive;
UIImage *separator;
//Setting imageWithRenderingMode: to imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal for iOS7 is key
if ([UIImage instancesRespondToSelector:#selector(imageWithRenderingMode:)]) {
onceActive = [[UIImage imageNamed:#"btn_onceActive"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
recurringActive = [[UIImage imageNamed:#"btn_recurringInactive"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
scheduledActive = [[UIImage imageNamed:#"btn_scheduledInactive"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
separator = [[UIImage imageNamed:#"separator"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
}
else {
onceActive = [UIImage imageNamed:#"btn_onceActive"];
recurringActive = [UIImage imageNamed:#"btn_recurringInactive"];
scheduledActive = [UIImage imageNamed:#"btn_scheduledInactive"];
separator = [UIImage imageNamed:#"separator"];
}
[self.theSegmentedControl setImage:onceActive forSegmentAtIndex:0];
[self.theSegmentedControl setImage:recurringActive forSegmentAtIndex:1];
[self.theSegmentedControl setImage:scheduledActive forSegmentAtIndex:2];
[self.theSegmentedControl setDividerImage:separator forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
UPDATE for Xcode 6/iOS 8
Now you can do it in Interface builder
Just add the image file in the asset catalog and set its "render as" original image instead of default
Xcode 5
The new UISegmented control uses the tint color to tint the images using the template mode.
You will need to render these images as original and not templates.
As suggested in the comments do this:
UIImage* onceActive = [UIImage imageNamed:#"btn_onceActive"];
if (IOS_7_MACRO)
onceActive = [onceActive imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
[self.theSegmentedControl setImage:onceActive forSegmentAtIndex:0];
Use this Code to set Image on Segment Control in iOS 7 with xCode 5.0
if ([UIImage instancesRespondToSelector:#selector(imageWithRenderingMode:)]) {
[segmentControl setImage:[[UIImage imageNamed:#"image.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] forSegmentAtIndex:0];
}
else {
[segmentControl setImage:[UIImage imageNamed:#"image.png"] forSegmentAtIndex:0];
}
It could be useful to create a category:
#interface UISegmentedControl (UISegmentedControlAdditions)
-(void)setImageRenderingMode:(UIImageRenderingMode)renderingMode;
#end
#implementation UISegmentedControl (UISegmentedControlAdditions)
-(void)setImageRenderingMode:(UIImageRenderingMode)renderingMode {
for (int index=0; index < [self numberOfSegments]; index++) {
UIImage * image = [self imageForSegmentAtIndex:index];
[self setImage:[image imageWithRenderingMode:renderingMode] forSegmentAtIndex:index];
}
}
... and just call
if([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
[colorSegmentedControl setImageRenderingMode:UIImageRenderingModeAlwaysOriginal];

change background image of navigation bar based on orientation

Is there a way to change the background image of navigation bar based on orientation? I tried using methods in the app delegate such as :
-(void)application:(UIApplication *)application didChangeStatusBarFrame:(CGRect)oldStatusBarFrame
{
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if(orientation == (UIInterfaceOrientationMaskPortrait)||orientation==(UIInterfaceOrientationMaskPortraitUpsideDown)){
UIImage *myImage = [UIImage imageNamed:#"borderP.png"];
UIImage * imageBottom = [UIImage imageNamed:#"bottomP.png"];
[[UIToolbar appearance] setBackgroundImage:imageBottom forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setBackgroundImage:myImage forBarMetrics:UIBarMetricsDefault];
[[UIToolbar appearance] setBackgroundImage:imageBottom forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
NSLog(#"******P******");
}
else if(orientation == (UIInterfaceOrientationMaskLandscapeLeft||orientation== UIInterfaceOrientationMaskLandscapeRight)){
UIImage *myImage = [UIImage imageNamed:#"borderL.png"];
UIImage * imageBottom = [UIImage imageNamed:#"borderL.png"];
[[UIToolbar appearance] setBackgroundImage:imageBottom forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setBackgroundImage:myImage forBarMetrics:UIBarMetricsDefault];
[[UIToolbar appearance] setBackgroundImage:imageBottom forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
NSLog(#"******L********");
}
}
but the back ground image does not change.
Any advice?
The appearance proxy only applies only to new instances. To modify an instance that already exists, you you need to call setBackgroundImage:forToolbarPosition:barMetrics: on it directly.

Root view controller is built in code - Wont resize for iPad

Im trying to convert my iphone app to ipad, all good until my root view controller. Its been built in code and no matter what I do I cant resize it/centre it. I have no nib for my Home page. Autoresize masks doesn't do anything, adding an iPad nib does nothing despite best efforts but continue to present the iphone screen in top left, and using if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) loads a a blank black iPad screen. I really dont know what to to now. If I set my screen elements to initWithFrame:[[UIScreen mainScreen] bounds]]; the artwork is distorted as its overstretched.
// Create the main view
UIView *mainView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
mainView.backgroundColor = [UIColor blackColor];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
UIImageView *textureBg = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 768.0f, 1024.0f)];
textureBg.image = [UIImage imageNamed:#"BgTexture"];
[textureBg addSubview:textureBg];
}
else {
// Add textured background
UIImageView *textureBg = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320.0f, 1024.0f)];
textureBg.image = [UIImage imageNamed:#"BgTexture"];
[textureBg addSubview:textureBg];
}
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
UIImageView *clipBg = [[UIImageView alloc] initWithFrame:CGRectMake(7.0f, 6.0f, 605.0f, 865.0f )];
clipBg.image = [UIImage imageNamed:#"BgHomeNew2"];
clipBg.userInteractionEnabled = YES;
}
else {
// Add clipboard background
UIImageView *clipBg = [[UIImageView alloc] initWithFrame:CGRectMake(7.0f, 6.0f, 305.0f, 465.0f )];
clipBg.image = [UIImage imageNamed:#"BgHomeNew2"];
clipBg.userInteractionEnabled = YES;
//[clipBg setAutoresizingMask:(UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleTopMargin )];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// Add about button to clipbg
UIButton *aboutButton = [UIButton buttonWithType:UIButtonTypeCustom];
aboutButton.frame = CGRectMake(240.0f, 90.0f, 31.0f, 33.0f);
[aboutButton setImage:[UIImage imageNamed:#"LabelButton"] forState:UIControlStateNormal];
[aboutButton addTarget:self action:#selector(aboutButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[aboutButton addSubview:aboutButton];
}
else {
// Add about button to clipbg
UIButton *aboutButton = [UIButton buttonWithType:UIButtonTypeCustom];
aboutButton.frame = CGRectMake(240.0f, 90.0f, 31.0f, 33.0f);
[aboutButton setImage:[UIImage imageNamed:#"LabelButton"] forState:UIControlStateNormal];
[aboutButton addTarget:self action:#selector(aboutButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[aboutButton addSubview:aboutButton];
}
How do I make an ipad view, for a universal app, where the root view controller is built in code? Im even open to the idea of simply centering the iphone screen in the middle of the ipad screen but as autoresing wont work its just stuck in the top left. This would be 2 mins in IB!
To summarise why wont the following code move the image to the center of the iPad screen?
UIImageView *clipBg = [[UIImageView alloc] initWithFrame:CGRectMake(7.0f, 6.0f, 305.0f, 465.0f )];
clipBg.image = [UIImage imageNamed:#"BgHomeNew2"];
clipBg.userInteractionEnabled = YES;
[clipBg setAutoresizingMask:(UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin)];
EDIT
Really dont know what im missing here, been on this a whole day now, Cant seem to add a xib retrospectively to an iphone screen built in code, so I will settle for centring objects in the middle of the screen when ipad is used rather than stuck in the top left all the time. That dosent work either.
Ok sorted it
Ive finally maged to add xibs now so I can adjust as necessary, I couldn't initialise the xibs before because I had missed this line of code in my rootview contoller
- (id)init
{
[[NSBundle mainBundle] loadNibNamed:#"ICHomeController" owner:self options:nil];

Could not set Image on Navigation bar only in "ios 5.0"

In my universal app,
I am setting an image on navigation bar...using **
objective c category...on UINavigationBar
**
The code works fine in ios 5.0 in iphone
*The code works fine in ios 4.3 in iPhone/iPad*
*But not working in **ios 5.0 iPad***
- (void) drawRect:(CGRect)rect
{
UIImage *image;
image = [UIImage imageNamed: #"Navigation.png"];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
[self setTintColor:[UIColor clearColor]];
NSLog(#"Draw Rect");
}
To set a BG image for navigation bar in iOS 5 you can use the below code
if ([self.navigationController.navigationBar respondsToSelector:#selector( setBackgroundImage:forBarMetrics:)]){
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:#"Navigation.png"] forBarMetrics:UIBarMetricsDefault];
}
But please keep in mind that this wont work in iOS 4. To make it work in both you also need to add a category to UINavigationBar
#implementation UINavigationBar (UINavigationBarCategory)
- (void)drawRect:(CGRect)rect {
UIImage *img = [UIImage imageNamed:#"Navigation.png"];
[img drawInRect:rect];
}
If you want to set the background application-wide you can use iOS5's UIAppearance.
[[UINavigationBar appearance] setBackgroundImage:X forBarMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setBackgroundImage:X forBarMetrics:UIBarMetricsLandscape];