UIEdgeInsets resizing Back button - ios

I'm trying to customize the back button of a UINavigationBar using the iOS 5 UIAppearance API. The image I want to use is this: https://www.dropbox.com/s/ce83rw0e3vs9dwo/bt-back.png and the code is the following:
// Customize back button items differently
UIEdgeInsets aInset = UIEdgeInsetsMake(10, 10, 10, 10);
UIImage *buttonBack30 = [[UIImage imageNamed:#"bt-back.png"] resizableImageWithCapInsets:aInset];
UIImage *buttonBack24 = [[UIImage imageNamed:#"bt-back.png"] resizableImageWithCapInsets:aInset];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:buttonBack30 forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:buttonBack24 forState:UIControlStateNormal barMetrics:UIBarMetricsLandscapePhone];
Now, the output of that code is the following: http://i.imgur.com/X6QBK.png
I know I have to set the UIEdgeInsets to a proper value, but I've being reading the documentation and it seems that it's only possible to preserve the edges and not the center, witch seems to be the thing I need to do.
Is there any way to preserve the center and not the edges? If not, what's the dimensions I have to generate the PNG so iOS doesn't stretch it?
Thanks a lot

Could you use the method
- (UIImage *)backButtonBackgroundImageForState:(UIControlState)state
barMetrics:(UIBarMetrics)barMetrics
to retrieve the back button's background image, retrieve its size property, and then use this for the size to make your custom image?

Related

How to change the background image of tab bar in Objective-C?

I am develop in objective-C. I want to change the tab bar background like the following picture:
And the code is like the following:
UIImage *tabBarBackground = [UIImage imageNamed:#"tabbaritem_background.png"];
[[UITabBar appearance] setBackgroundImage:tabBarBackground];
But after setting the background image , the background is not at the correct place like the following:
The background image should be place at the bottom like the background in above picture.
Did I missing something ? Can someone help me ?
Thanks in advance.
I think is somewhere you go wrong, check if is this steps:
In the storyboard change the ViewController's background color for test.
Embed the ViewController in Tab Bar Controller
In the ViewController.m you can set the tabbar bacground color:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[[UITabBar appearance] setBackgroundColor:[UIColor grayColor]]; // Here you can set the converted color form image, make sure the imageSize fit.
}
The result is below:
I think the method - (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingMode you can try, because your backgroudimage's size is not equal to tabbar'size.
Try this method to change your image to a ScaleImage.
+(UIImage *)getScaleImageNamed:(NSString *)name{
UIImage *nomalImage = [UIImage imageNamed:name];
CGFloat hInset = floorf(nomalImage.size.width / 2);
CGFloat vInset = floorf(nomalImage.size.height / 2);
UIImage *res = [nomalImage resizableImageWithCapInsets:UIEdgeInsetsMake(vInset, hInset, vInset, hInset)];
return res;
}
Steps you may miss, hope that can help.
Make sure you have imported the background image (e.g. in Assets.xcassets)
Use resizableImageWithCapInsets: to resize the background image
Put the UIAppearance settings in AppDelegate.m:
[[UITabBar appearance] setBackgroundImage:[[UIImage imageNamed:#"tabbaritem_background.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)]];

UIImage's resizableImageWithCapInsets places a shadow on image

I'm having trouble customising an UISegmentedControl: I've subclassed it I'm setting it's background for both the selected state and the unselected state like this:
#define kEdgeInsets UIEdgeInsetsMake(18, 18, 18, 18)
UIImage *grayImage = [[UIImage v_imageNamed:#"gray_rect"] resizableImageWithCapInsets:kEdgeInsets];
[self setBackgroundImage:grayImage
forState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
UIImage *greenImage = [[UIImage v_imageNamed:#"green_rect"] resizableImageWithCapInsets:kEdgeInsets];
[self setBackgroundImage:greenImage
forState:UIControlStateSelected
barMetrics:UIBarMetricsDefault];
[self setTintColor:[UIColor colorWithRed:0.506 green:0.514 blue:0.525 alpha:1.000]];
Where this are the PNGs I'm using
Now, when I execute this code, I get a weird shadow on the segmented control, which is not what we want. This is what the output looks like
Which is very weird, because there is no shadow on the original images, nor does UISegmentedControl add one (as far as I know).
Further checking, I noticed that if I removed the resizableImageWithCapInsets: call, the image looks distorted (as one should expect) but without the shadow.
Any ideas? because I'm literally going mad over this, since I don't have this problem when using resizableImageWithCapInsets: with UIButton
Thanks a lot!
I figured it out.
Turns out the segmented controller's frame is of 44pts height, and the background images was 75ptsx75pts. Since i've set the image's top and bottom inset to 18pts, the OS was taking the image's top and bottom 18pts and resizing it, ignoring the rest. Here is the fun part, since the image has a gradient, the rest of the image is ignored and it the control is colored like that.
In order to use images with vertical gradients you must use a base PNG with the exact same height as your control (http://useyourloaf.com/blog/2012/07/05/customizing-appearance-with-resizable-images.html)
This is what I did, resize the image to 44x44pts and change the insets to UIEdgeInsetsMake(0, 10, 0, 10) denoting that the image can't have to be resized vertically

How do I an image at a specific location in a navigation bar?

Im customizing my navbars so they all have a logo in them. I want to add the logo right around here:
I know navbars have a background image property but that would stretch it to the whole navbar. I just want it there! :)
So far Ive tried this:
UIImage *gradientImage44 = [[UIImage imageNamed:#"NavBar25High"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
UIImage *gradientImage32 = [[UIImage imageNamed:#"NavBar25High"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
// Set the background image for *all* UINavigationBars
[[UINavigationBar appearance] setBackgroundImage:gradientImage44 forBarMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setBackgroundImage:gradientImage32 forBarMetrics:UIBarMetricsLandscapePhone];
But thats for gradients because as I mentioned, it uses the image as a background image :(
I would allocate an ImageView using CGRectMake to the specific location you want it and add that image view to the view of the UINavigationController.
Like this:
Declare the image
UIImage *myImage =[UIImage imageNamed:#"header.png"];
Allocate the image view
myImageView_tools = [[UIImageView alloc] initWithFrame:CGRectMake(97.5, 20, 125, 45)];
Set the image as the image of the imageview
myImageView_tools.image = myImage;
Add this to your navbar.
[nameofyournavbar.view addSubview:myImageView_tools];
In my code I happened to add it to the RootViewController instead of the NavigationBar but I would imagine it would work just the same.
How about adding the image as the custom view of a UIBarButtonItem. Maybe using a UIBarButtonSystemItemFixedSpace item with a specified width.

setBackButtonBackgroundImage with weird appearance

using this in AppDelegate.m for my custom NavBar:
UIImage *NavigationPortraitBackground = [[UIImage imageNamed:#"gradient_main"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
[[UINavigationBar appearance] setBackgroundImage:NavigationPortraitBackground forBarMetrics:UIBarMetricsDefault];
UIImage *barBackBtnImg = [[UIImage imageNamed:#"btn_nav_default.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:barBackBtnImg forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
results in:
As you can see the button seems to be repeated. Button dimensions are 61x30. And the text is not centered.
If the text is shorter (e.g. Menu) the button image is cut off and if text is longer, then button is repeating.
Similar problem with buttons that have a smaller icon (30x30). The button shows fine but I can click in the button outside of the image :(
The root of your problem is that you are providing a resizeable image without UIEdgeInsets and without specifying the resizing style. The text on your UIBarButtonItem is actually centered! If you measure the distance on both sides of the text, you'll realize that it's the same.
If you look at the image you provide for the UIBarButtonItem:
[[UIImage imageNamed:#"btn_nav_default.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
You're telling iOS that #"btn_nav_default.png" is a resizeable image and that it should tile. It's basically taking copies of your image and placing them side by side until the full width is covered. If you look at UIImage's Documentation you'll see that the default behaviour for resizableImageWithCapInsets is to tile. You will want to call resizableImageWithCapInsets:resizingMode: and pass in UIImageResizingModeStretch for your resizing mode.
That being said, that won't be enough. What you'll see after that is that the entire image is stretched, completely destroying your nice rounded corners. You need to provide UIEdgeInsets that tell UIImage that "you cannot stretch this section". In this case, providing UIEdgeInsets of UIEdgeInsetsMake(0.0f, 10.0f, 0.0f, 10.0f) (or something similar) will work.
If you're not interested in the long explanation, copy paste this code (no guarantees that this compiles though...):
[[UIImage imageNamed:#"btn_nav_default.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0.0f, 10.0f, 0.0f, 10.0f) resizingMode:UIImageResizingModeStretch];
You can try to play with
[[UIBarButtonItem appearance] setBackButtonBackgroundVerticalPositionAdjustment:5 forBarMetrics:UIBarMetricsDefault];
in ios 5 after you put the insets

iOS6 music and clock app tab bar with segmented pressed buttons [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
Does anyone know how to style their uitabbar like Apple in Music and Clock apps on the iPad?
I have been searching the web over but I can't find much out there.
Thanks
Edit:
Rephrasing, I'm trying to understand how to go about setting this up. I've been trying using uitabbarcontroller but I wasn't sure if this was a manipulated style of uitabbaritems or if it was using segmented controls. It seems to be a common view in Apple's new apps, but I wasn't sure how much customization was needed to achieve the effect. If I wanted to have two unique views selectable in a similar fashion to Apple's Music and Clock apps, would I approach as follows:
UIViewController (root)
UIToolbar
Segmented Control
Button 1
Loads ViewController1
Button 2
Loads ViewController2
That is a UISegmentedControl. You can style its appearance using the following methods:
/* Default tintColor is nil. Only used if style is UISegmentedControlStyleBar or UISegmentedControlStyleBezeled
*/
#property(nonatomic,retain) UIColor *tintColor UI_APPEARANCE_SELECTOR;
/* If backgroundImage is an image returned from -[UIImage resizableImageWithCapInsets:] the cap widths will be calculated from that information, otherwise, the cap width will be calculated by subtracting one from the image's width then dividing by 2. The cap widths will also be used as the margins for text placement. To adjust the margin use the margin adjustment methods.
In general, you should specify a value for the normal state to be used by other states which don't have a custom value set.
Similarly, when a property is dependent on the bar metrics (on the iPhone in landscape orientation, bars have a different height from standard), be sure to specify a value for UIBarMetricsDefault.
In the case of the segmented control, appearance properties for UIBarMetricsLandscapePhone are only respected for segmented controls in the smaller navigation and toolbars that are used in landscape orientation on the iPhone.
*/
- (void)setBackgroundImage:(UIImage *)backgroundImage forState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
- (UIImage *)backgroundImageForState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
/* To customize the segmented control appearance you will need to provide divider images to go between two unselected segments (leftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal), selected on the left and unselected on the right (leftSegmentState:UIControlStateSelected rightSegmentState:UIControlStateNormal), and unselected on the left and selected on the right (leftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateSelected).
*/
- (void)setDividerImage:(UIImage *)dividerImage forLeftSegmentState:(UIControlState)leftState rightSegmentState:(UIControlState)rightState barMetrics:(UIBarMetrics)barMetrics NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
- (UIImage *)dividerImageForLeftSegmentState:(UIControlState)leftState rightSegmentState:(UIControlState)rightState barMetrics:(UIBarMetrics)barMetrics NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
/* You may specify the font, text color, text shadow color, and text shadow offset for the title in the text attributes dictionary, using the keys found in UIStringDrawing.h.
*/
- (void)setTitleTextAttributes:(NSDictionary *)attributes forState:(UIControlState)state NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
- (NSDictionary *)titleTextAttributesForState:(UIControlState)state NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
/* For adjusting the position of a title or image within the given segment of a segmented control.
*/
- (void)setContentPositionAdjustment:(UIOffset)adjustment forSegmentType:(UISegmentedControlSegment)leftCenterRightOrAlone barMetrics:(UIBarMetrics)barMetrics NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
- (UIOffset)contentPositionAdjustmentForSegmentType:(UISegmentedControlSegment)leftCenterRightOrAlone barMetrics:(UIBarMetrics)barMetrics NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
This example sets the background and the divider images for the different selection states (using the appearance proxy to change the appearance of all segmented controls):
UIImage *segmentSelected =
[[UIImage imageNamed:#"segcontrol_sel.png"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 15)];
UIImage *segmentUnselected =
[[UIImage imageNamed:#"segcontrol_uns.png"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 15)];
UIImage *segmentSelectedUnselected =
[UIImage imageNamed:#"segcontrol_sel-uns.png"];
UIImage *segUnselectedSelected =
[UIImage imageNamed:#"segcontrol_uns-sel.png"];
UIImage *segmentUnselectedUnselected =
[UIImage imageNamed:#"segcontrol_uns-uns.png"];
[[UISegmentedControl appearance] setBackgroundImage:segmentUnselected
forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setBackgroundImage:segmentSelected
forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setDividerImage:segmentUnselectedUnselected
forLeftSegmentState:UIControlStateNormal
rightSegmentState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setDividerImage:segmentSelectedUnselected
forLeftSegmentState:UIControlStateSelected
rightSegmentState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance]
setDividerImage:segUnselectedSelected
forLeftSegmentState:UIControlStateNormal
rightSegmentState:UIControlStateSelected
barMetrics:UIBarMetricsDefault];

Resources