iPhone UINavigationBar - Set width and margin of rightBarButtonItem - ios

I have a background image for a button, with the dimensions of 80x30 pixels.
I use the code below to set the background in my view-controller, and the result is this:
As you can see, the corners and the top of the right button is messed up.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
UIImage *favoriteBtnImgNormal = [[UIImage imageNamed:#"favorite-btn-normal"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 30, 30, 0)];
UIImage *favoriteBtnImgTouch = [[UIImage imageNamed:#"favorite-btn-touch"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 30, 30, 0)];
[self.navigationItem.rightBarButtonItem setBackgroundImage:favoriteBtnImgNormal forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[self.navigationItem.rightBarButtonItem setBackgroundImage:favoriteBtnImgTouch forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault];
[self.navigationItem.rightBarButtonItem setBackgroundImage:favoriteBtnImgTouch forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
[self.navigationItem.rightBarButtonItem setTitlePositionAdjustment:UIOffsetMake(-10.0, 0.0) forBarMetrics:UIBarMetricsDefault];
}
Note that I do this in a single view-controller, I use the appearance API to set general styles. But here I want to override the general appearance.
If I just get the images without the resizable-stuff, it looks like this:
Now the edges and corners are fine, but the button is too large.
I'm sure I'm doing this all wrong, so I need someone to point out what I could do to scale buttons correctly?

UIImage *image = [UIImage imageNamed:#"YourImage"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.bounds = CGRectMake( 0, 0, image.size.width, image.size.height );
[button setImage:image forState:UIControlStateNormal];
[button addTarget:self action:#selector(YourAction) forControlEvents:UIControlEventTouchUpInside];
button.contentEdgeInsets = (UIEdgeInsets){.right=-10};
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:button] autorelease];

Related

UINavigationItems Stretching in iOS11

I'm updating an app to ensure that it works as expected in iOS11. The only issue I've run into is that the navigation bar looks quite different in iOS11. The position of the elements and size is not the same between versions. I've looked at my code and i'm explicitly setting frame sizes and edge insets, why are these values are not respected in iOS11?
//-- Create Right Navigation Item Buttons
// create kabob btn
UIButton *kabobBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[kabobBtn addTarget:self action:#selector(viewUsersClicked:)forControlEvents:UIControlEventTouchUpInside];
kabobBtn.clipsToBounds = YES;
[kabobBtn setImage:[UIImage imageNamed:#"KabobMenu2_0071bc_Right.png"]
forState:UIControlStateNormal];
[kabobBtn.imageView setContentMode:UIViewContentModeScaleAspectFit];
[kabobBtn setFrame:CGRectMake(0, 0, 32, 32)];
// create user profile button
UIButton *userBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[userBtn setImage:[UIImage imageNamed:#"people.png"]
forState:UIControlStateNormal];
[userBtn addTarget:self action:#selector(viewUserProfileClicked:)forControlEvents:UIControlEventTouchUpInside];
[userBtn setFrame:CGRectMake(0, 0, 38, 38)];
userBtn.clipsToBounds = YES;
[userBtn.layer setCornerRadius:(38/2)];
[userBtn.layer setMasksToBounds:YES];
[userBtn.layer setBorderColor:[[UIColor blackColor]CGColor]];
[userBtn.layer setBorderWidth:1];
self.userPictureURL = [defaults objectForKey:#"userPicture"];
[userBtn setImage:[UIImage imageNamed:#"defaultUserImage.png"] forState:UIControlStateNormal];
[userBtn setContentMode:UIViewContentModeScaleAspectFill];
[userBtn setBackgroundColor:[UIColor clearColor]];
// add buttons to bar button items
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithCustomView:kabobBtn];
UIBarButtonItem *barButton2 = [[UIBarButtonItem alloc] initWithCustomView:userBtn];
// add bar button items to right bar button item array
self.navigationItem.rightBarButtonItems = #[barButton,barButton2];
//-- Create Left Hamburger Button
UIButton *customOpen = [UIButton buttonWithType:UIButtonTypeCustom];
[customOpen setFrame:CGRectMake(0, 0, 30, 44)];
[customOpen setImage:[UIImage imageNamed:#"hamburger.png"] forState:UIControlStateNormal];
[customOpen setImageEdgeInsets:UIEdgeInsetsMake(10, -5, 16, 10)];
UIBarButtonItem *openItem = [[UIBarButtonItem alloc] initWithCustomView:customOpen];
if(self.showHamburger){
self.navigationItem.leftBarButtonItem = openItem;
}else{
self.navigationItem.leftBarButtonItem = nil;
}
Apparently iOS 11 uses autolayout for nav bar buttons. Use auto layout constraints to set button width and height.
[userBtn.widthAnchor constraintEqualToConstant:38.f].active = YES;
[userBtn.heightAnchor constraintEqualToConstant:38.f].active = YES;
This should fix the stretching issue.
Thanks to this answer

UINavigationBar - Change Height / Add Big Button

I need to change the height of my Navigation Bar and add a custom Image button to the top left corner. I am part way there, but lost now on getting the custom Image button in the right position. Here is what I have:
To adjust the height I have created a UINavBar category with one method as follows:
#implementation UINavigationBar (myNavBar)
- (CGSize)sizeThatFits:(CGSize)size {
CGSize newSize = CGSizeMake(768,80);
return newSize;
}
#end
I have also created a UINavigationController subclass to modify the button. Here is the viewDidLoad from that class:
UIImage *navBackgroundImage = [UIImage imageNamed:#"bar"];
[[UINavigationBar appearance] setBackgroundImage:navBackgroundImage forBarMetrics:UIBarMetricsDefault];
// Change the appearance of back button
UIImage *backButtonImage = [[UIImage imageNamed:#"back_off"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 13, 0, 6)];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
// Change the appearance of other navigation button
UIImage *barButtonImage = [[UIImage imageNamed:#"menu_off"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 6, 0, 6)];
[[UIBarButtonItem appearance] setBackgroundImage:barButtonImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
So far this solution resizes the top nav bar, but positions my button in a weird position. Here are what I want vs. what is happening:
What I want
What I get
I have a UIBarButtonItem Category that I use which has an offset property:
UIBarButtonItem+CustomImage.h
#interface UIBarButtonItem (CustomImage)
+ (UIBarButtonItem*)barItemWithImage:(UIImage*)image target:(id)target action:(SEL)action offset:(CGPoint)offset;
#end
UIBarButtonItem+CustomImage.m
#import "UIBarButtonItem+CustomImage.h"
#implementation UIBarButtonItem (CustomImage)
+ (UIBarButtonItem *)barItemWithImage:(UIImage *)image target:(id)target action:(SEL)action offset:(CGPoint)offset {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:image forState:UIControlStateNormal];
[button setFrame:CGRectMake(0.0, 0.0, image.size.width, image.size.height)];
[button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
[button setBounds:CGRectOffset(button.bounds, 0.0, -10.0)];
UIView *container = [[UIView alloc] initWithFrame:button.frame];
[container setBounds:CGRectOffset(container.bounds, offset.x, offset.y)];
[container addSubview:button];
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:container];
return item;
}
#end
Example Usage
#import "UIBarButtonItem+CustomImage.h"
UIBarButtonItem *settingsButton = [UIBarButtonItem barItemWithImage:settingsImage
target:self
action:#selector(revealSettings:)
offset:CGPointMake(0.0, 0.0)];
[self.navigationItem setLeftBarButtonItem:settingsButton];

Custom UIBarButtonItem

I am trying to create a custom UIBarbuttonItem that uses just a png with transparency so that I only have an icon as button. When I try to set the button image, set the background as white, and set the style to Plain I still get an inner shadow and black border around it.
What gives?
I have tried the below code and it still puts the black border around it.
UIImage *background = [UIImage imageNamed:#"Dismiss_normal.png"];
UIImage *backgroundSelected = [UIImage imageNamed:#"Dismiss_selected.png"];
self.closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.closeButton addTarget:self action:#selector(closeButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; //adding action
[self.closeButton setBackgroundImage:background forState:UIControlStateNormal];
[self.closeButton setBackgroundImage:backgroundSelected forState:UIControlStateSelected];
self.closeButton.frame = CGRectMake(0 ,0,background.size.width, background.size.height);
self.closeButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.closeButton];
self.navigationItem.leftBarButtonItem = self.closeButtonItem;
What I noticed is if I do a modal segue the button, with the code above still has a black border around it, but if I do a push segue it doesn't? WTF?
You must set the button type to Custom and the icon image to the button background.
example code:
UIImage *background = [UIImage imageNamed:#"icon.png"];
UIImage *backgroundSelected = [UIImage imageNamed:#"icon_selected.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:#selector(checkButtonTapped:event:) forControlEvents:UIControlEventTouchUpInside]; //adding action
[button setBackgroundImage:background forState:UIControlStateNormal];
[button setBackgroundImage:backgroundSelected forState:UIControlStateSelected];
button.frame = CGRectMake(0 ,0,35,35);
Then set this button to your BarButtonItem like this:
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithCustomView:button];
self.navigationItem.leftBarButtonItem = barButton;
I understood your problem.
When you actually push a UIViewController it will be a part of existing UINavigationController. So the UINavigationBar retains. But when you use ModalViewController its just another UIViewController kind of "added" to your existing UIViewController. So the UINavigationBar won't be there.
But you can add another UINavigationBar from xib and add a UIButton. But don't directly add the UIButton, if you do so it will automatically convert to UIBarButton making it bordered.
So first drag a normal UIButton to your UIView(not navigation bar). Change it to custom and add UIImage to it using Attribute Inspector. Then drag that image to your custom created UINavigationBar. It will work as I tried it just now. You can see the screen shot attached below.
This will update ALL back buttons and navigation bars throughout the app.
I have used the Following code to set Custom Navigation back button
UIImage *imgBack = [[UIImage imageNamed:#"nav_back.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(-6, 22, -6, 0)];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:imgBack forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
and the Following code for Setting background image on navigation bar.
UIImage *navBackgroundImage = [UIImage imageNamed:#"nav_bar.png"];
[[UINavigationBar appearance] setBackgroundImage:navBackgroundImage forBarMetrics:UIBarMetricsDefault];
Try use [UIBarButtonItem initWithCustomView]
UIImage *menuButtonImage = [UIImage imageNamed:#"list.png"];// set your image Name here
UIButton *btnToggle = [UIButton buttonWithType:UIButtonTypeCustom];
[btnToggle setImage:menuButtonImage forState:UIControlStateNormal];
btnToggle.frame = CGRectMake(0, 0, menuButtonImage.size.width, menuButtonImage.size.height);
UIBarButtonItem *menuBarButton = [[UIBarButtonItem alloc] initWithCustomView:btnToggle];
self.navigationItem.leftBarButtonItem = menuBarButton;
I personally like FlatUIKit's approach by just flattening out the entire UI through UIAppearance
Essentially, you'd do something like:
UIImage *backButtonPortraitImage = [UIImage backButtonImageWithColor:color barMetrics:UIBarMetricsDefault cornerRadius:cornerRadius];
UIImage *highlightedBackButtonPortraitImage = [UIImage backButtonImageWithColor:highlightedColor barMetrics:UIBarMetricsDefault cornerRadius:cornerRadius];
[appearance setBackButtonBackgroundImage:backButtonPortraitImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[appearance setBackButtonBackgroundImage:highlightedBackButtonPortraitImage forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault];
UIImage *buttonImageNormal = [UIImage imageWithColor:color cornerRadius:cornerRadius];
UIImage *buttonImageHightlighted = [UIImage imageWithColor:highlightedColor cornerRadius:cornerRadius];
[appearance setBackgroundImage:buttonImageNormal forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[appearance setBackgroundImage:buttonImageHightlighted forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault];
Try this code..
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *btnImage = [UIImage imageNamed:#"bg"];
[button setImage:btnImage forState:UIControlStateNormal];
button.frame = CGRectMake(0, 0, btnImage.size.width, btnImage.size.height);
[button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
UIImage *icon = [UIImage imageNamed:#"icon"]
UIImageView *iconView = [[UIImageView alloc] initWithImage:icon];
iconView.frame = CGRectMake(0, 0, icon.size.width, icon.size.height);
[button addSubview:iconView];
iconView..userInteractionEnabled=NO;
[iconView centerBothDirections];
[iconView release];
UIBarButtonItem *barbtn = [[[UIBarButtonItem alloc] initWithCustomView:button] autorelease];
self.navigationItem.leftBarButtonItem =barbtn

Customizing UIBarButton makes it too big

So when I try to set a custom color to a UIBarButton, it causes the displayed button to be too big and it extends down past the NavigationBar and into the main view of the app. Is there an easy way to fix this? Here is my code:
UIImage *buttonColor = [[UIImage imageNamed:#"blue-background.jpg"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 5)];
[[UIBarButtonItem appearance] setBackgroundImage:buttonColor forState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
try playing with the values of the UIEdgeInsetsMake function.
in one of my apps it looks like this;
UIImage *backbuttonimage = [[UIImage imageNamed:#"backbutton.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 10)];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backbuttonimage
forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
it made it as i wanted... if you have any problems i would like you to tell me and if you can add a photo of how it looks for me to understand better the problem.
these are my values for my app:
UIEdgeInsetsMake(0, 15, 0, 10)
have a nice day :)
This is how i make custom UIBarButtonItem and it works perfect for me. Try this:
UIButton *postView = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 61, 30)];
[postView setTitle:#"Post" forState:UIControlStateNormal];
[postView addTarget:self action:#selector(showAddPost) forControlEvents:UIControlEventTouchUpInside];
[postView setBackgroundImage:[UIImage imageNamed:#"bbi_texture.png"] forState:UIControlStateNormal];
[postView setBackgroundImage:[UIImage imageNamed:#"bbi_texture.png"] forState:UIControlStateHighlighted];
UIBarButtonItem *postButton = [[UIBarButtonItem alloc] initWithCustomView:postView];
[self.navigationItem setRightBarButtonItem:postButton];

How to have iOS set a gradient on UIBarButtonItem image?

just wondering, I customised the UIBarButtonItems the following way
+ (UIBarButtonItem *)createBarButtonItemWithTitle:(NSString *)t target:(id)tgt action:(SEL)a
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *buttonImage = [[UIImage imageNamed:#"blabla.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 10, 0, 10)];
CGRect buttonFrame = [button frame];
buttonFrame.size.width = 35;
buttonFrame.size.height = buttonImage.size.height;
[button setFrame:buttonFrame];
[button setBackgroundImage:buttonImage forState:UIControlStateNormal];
[button addTarget:tgt action:a forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
return buttonItem ;
}
But now, I don't have the shading/glossy effect on the button background image....
Is there a way to have it done automatically, or I have to do it programatically ?
EDIT:
To totally customize the bar button in such a way you'd need to provide something other than the flat green image in "blabla.png".
A different way to handle this would be to create a bordered style button with your image. Something like:
UIBarButtonItem* barButton = [UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"blabla.png"] style:UIBarButtonItemStyleBordered target:tgt selector:a];
The UIBarButtonItemStyleBordered style gives it the 3D raised button-y look. You can tint its appearance to match your bar if desired.

Resources