Adding left and right UIBarButtonItem in navigation bar - ios

I'm trying to create a standard navigation bar programmatically using UINavigationItem setLeftBarButtonItem and setRightBarButtonItem
I want to have NavigationItem that looks like
[ < BACKTEXT FWDTEXT > ]
I want to have a constant space between my images (arrow) and device edges.
I would also want to have a constant space between images and texts.
I created a category over UIBarButtonItem and added two method backButtonWith and fwdButtonWith
I read #Split useful answer that explained how to solve the right button
button.titleEdgeInsets = UIEdgeInsetsMake(0, - button.imageView.frame.size.width, 0, button.imageView.frame.size.width);
button.imageEdgeInsets = UIEdgeInsetsMake(0, button.titleLabel.frame.size.width, 0, -button.titleLabel.frame.size.width);
But I'm having a hard time resolving the back button.
Here is my code
- (UIBarButtonItem *)buttonWith:(BOOL) directionLeft title:(NSString *)title image:(UIImage *) buttonImage tintColor:(UIColor *)color target:(id)target andAction:(SEL)action{
UIButton *barButton;
barButton = [UIButton buttonWithType:UIButtonTypeCustom];
float buttonWidth = 130.0f;
[barButton setFrame:CGRectMake(0, 0, buttonWidth, 20.5f)];
[barButton setTitle:title forState:UIControlStateNormal];
[barButton setTitleColor:color forState:UIControlStateNormal];
const CGFloat* components = CGColorGetComponents(color.CGColor);
[barButton setTitleColor:[UIColor colorWithRed:components[0] green:components[1] blue:components[2] alpha:0.3f] forState:UIControlStateHighlighted];
UIEdgeInsets titleEdgeInsets;
UIEdgeInsets imageEdgeInsets;
UIImage *image = [self image:buttonImage tintedWithColor:color fraction:0.0];
[barButton setImage:image forState:UIControlStateNormal];
[barButton setImage:[self image:image byApplyingAlpha:0.3] forState:UIControlStateHighlighted];
[barButton addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
if(directionLeft == YES){
titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0);//THIS PARAMS SHOULD BE CONFIGURED
imageEdgeInsets = UIEdgeInsetsMake(0,0,0,0);
}else{
titleEdgeInsets = UIEdgeInsetsMake(0, -barButton.imageView.frame.size.width, 0, barButton.imageView.frame.size.width);
imageEdgeInsets = UIEdgeInsetsMake(0, barButton.titleLabel.frame.size.width, 0, -barButton.titleLabel.frame.size.width);
}
barButton.imageEdgeInsets = imageEdgeInsets;
barButton.titleEdgeInsets = titleEdgeInsets;
UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:barButton];
return barButtonItem;
}

The back button which you set to UINavigationItem appears on the next navigation item which is pushed to the navigation bar. You won't see in on the current navigation item. Also, as I remember, back button is not able to contain custom view, it should be plain UIBarButtonItem.
You can customize the appearance of your back button with
[UIBarButtonItem appearanceWhenContainedIn:<YourNavigationBar.class>]
or with general appearance
[UIBarButtonItem appearance]
For details on back button item appearance customization, please check out this question

Related

iOS - make UIImage take the same size as UIButton

I create a custom bar button using
+ (UIBarButtonItem *)barBtnItem:(id)target action:(SEL)action imageName:(NSString *)imageName frame:(CGRect)frame
{
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
[btn addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
[btn setFrame:frame];
UIBarButtonItem *barBtn = [[UIBarButtonItem alloc] initWithCustomView:btn];
return barBtn;
}
The frame is of size
CGRectMake(0, 0, 22, 22)
However, I think due to aspect ratio, my image gets smaller but is correctly centered in the UIButton
However, I want the image to become the same size as of UIButton.
Can I do that?
I used XCode 7 and tried its slicing feature. But I could not make it work.
If I could do it via code?
I also looked at UIEdgeinsets but I do not fully understand cap/insets concepts.
Set the content mode of the button to UIViewContentModeScaleToFill.
btn.imageView.contentMode = UIViewContentModeScaleToFill
btn.imageView.frame = btn.bounds
check after write below code :
btn.contentMode= UIViewContentModeScaleToFill;
btn.contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0);
btn.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0);
Still not work then try below line of code. Set background image of UIButton instead of image.
+ (UIBarButtonItem *)barBtnItem:(id)target action:(SEL)action imageName:(NSString *)imageName frame:(CGRect)frame
{
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setBackgroundImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
[btn addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
[btn setFrame:frame];
UIBarButtonItem *barBtn = [[UIBarButtonItem alloc] initWithCustomView:btn];
return barBtn;
}
if not work use below line of code :
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:imageName] style:UIBarButtonItemStylePlain target:self action:#selector(handleBack:)];
you can do it through AutoLayouts !!! set image Constraints from top , bottom , left , right equal to Button !!

It's hard to click on Bar button Item

I've created custom back bar button. And I added an UIview because I have to change position of it within bar.
UIImage *backButtonImage = [UIImage imageNamed:#"backBtnWhite"];
_backButton = [UIButton buttonWithType:UIButtonTypeCustom];
_backButton.exclusiveTouch = YES;
[_backButton setImage:backButtonImage forState:UIControlStateNormal];
[_backButton setImage:backButtonImage forState:UIControlStateHighlighted];
[_backButton addTarget:self action:#selector(back) forControlEvents:UIControlEventTouchUpInside];
_backButton.frame = CGRectMake(-4.0, 7.0, 40, 40);
UIView * view = [[UIView alloc] initWithFrame:CGRectMake(-4.0, 7.0, backButtonImage.size.width, backButtonImage.size.height)];
[view addSubview:_backButton];
UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:view];
self.navigationItem.rightBarButtonItem = barButtonItem;
But after that I've added UIView it became difficult to click on it.
I've tried to change button area, but it didn't give results.
It seems like you specify incorrect frame for _button or/and view and this changes the tap region. Try to set different background color for _backButton and view. This will show you if frames are in positions that you expect.
If you try to adjust image position by specifying these frames - its more correct to use properties of UIButton like imageEdgeInsets and titleEdgeInsets.

Changing vertical position of UIBarButtonItem on iOS 8.2

Here is my navigation bar
I had a problem about changing vertical position of Settings UIBarButtonItem on my navigation bar. I would like to move the button item "Settings" down
Here is my code
UIBarButtonItem *settingsItem = [[UIBarButtonItem alloc] initWithTitle:#"Settings" style:UIBarButtonItemStylePlain target:self action:nil];
self.navItem.rightBarButtonItem = settingsItem;
[[UIBarButtonItem appearance] setTitlePositionAdjustment:UIOffsetMake(0,-10) forBarMetrics:UIBarMetricsDefault];
I had tried it again and again. It seemed that it's not work
Could anyone suggest me how to move the button item "Settings" down ?
You can easily add a Custom Button to your NavigationBarItem, Here is the way,
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; //create custom Button
[button setTitle:#"Settings" forState:UIControlStateNormal];
[button.titleLabel setFont:[UIFont systemFontOfSize:14.0]];
[button setTitleColor:[UIColor colorWithRed:179.0/255.0 green:40.0/255.0 blue:18.0/255.0 alpha:1] forState:UIControlStateNormal];
button.frame = CGRectMake(0, 0, 50, 20); //Button frame
[button addTarget:self action:#selector(yourCustomSelectorHere) forControlEvents:UIControlEventTouchUpInside]; //Add action method to the button here
UIView *backButtonView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 63, 33)];
backButtonView.bounds = CGRectOffset(backButtonView.bounds, -14, -7);
[backButtonView addSubview:button];
UIBarButtonItem *barBtnItem = [[UIBarButtonItem alloc]initWithCustomView: backButtonView]; //set button as UIBarButtonItem
self.navigationItem.rightBarButtonItem = barBtnItem; //set barBtnItem to rightBarButtonItem
By changing backButtonView.bounds values you can change the origin of the Button
Cited from apple's documentation on UIAppearance protocol
iOS applies appearance changes when a view enters a window, it doesn’t
change the appearance of a view that’s already in a window.
So if your code of setting UIBarButtonItem's appearance is after the navigationItem assignment code. It won't work

UINavigationBar barButtonItem change back button image and title

Is it possible to change the back button on a UINavigationBar and change the title?
When I try to set the customView property, I get an image right next to the default button.
I use this code
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithImage:backButtonImage landscapeImagePhone:nil style:UIBarButtonItemStylePlain target:nil action:nil];
I want the title to be "Back" which is easy enough to do in Storyboard. But the problem is that no matter if I use code above or use customView property, the default back button remains.
You can add a UIImage to the UIButton. And, then use it as a custom back button. Here's a quick example:
// Custom image
UIImage *backButtonImage = [UIImage imageNamed:#"button-background-image.png"];
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
[backButton setFrame:CGRectMake(0, 0, 100, 30)];
[backButton setBackgroundImage:backButtonImage forState:UIControlStateNormal];
// Custom title
[backButton setTitle:#"Back" forState:UIControlStateNormal];
[backButton setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
[backButton addTarget:self action:#selector(barPayButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[backButton setShowsTouchWhenHighlighted:NO];
UIBarButtonItem *buttonOnBar =[[UIBarButtonItem alloc] initWithCustomView:backButton];
self.navigationItem.leftBarButtonItem = buttonOnBar;
Note: You will loose the chevron (system-provided back arrow) which was introduced in iOS7. It goes as a title and chevron together presenting your previous view controller.
Update:
You can also use UIEdgeInsets to resize your image intelligently.
UIEdgeInsets edgeInsets = UIEdgeInsetsMake(0, 0, 15, 10);
UIImage *backButtonImage = [[UIImage imageNamed:#"button-background-image.png"] resizableImageWithCapInsets:edgeInsets];
You can achieve what you want by setting the navigationItem.leftBarButtonItem of the view controller that's being pushed to the custom bar button item with the look you want. Good Luck!

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