back button uinavigationcontroller - ios

I'm trying to make a custom back button to pop back to parent in nav controller. I understand I should've made the back button in parent controller itself
self.navigationItem.backBarButtonItem= backBarButton
The button was just default button with custom text, but it worked. None of formatting or fonts showed up.
So instead I made a custom leftBarButton in child VC:
UIButton *backBtn= [[UIButton alloc] init];
backBtn.backgroundColor = [UIColor clearColor];
backBtn.titleLabel.font = [UIFont fontWithName:#"CrimeFighter BB" size:20];
backBtn.titleLabel.textColor = [UIColor whiteColor];
backBtn.titleLabel.text = #"back";
[backBtn addTarget:self action:#selector(pop) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *backBarButton = [[UIBarButtonItem alloc] initWithCustomView:backBtn];
self.navigationItem.leftBarButtonItem = backBarButton;
Its working fine, but the button is not visible at all!

New attempt:
Doing an alloc & init on a UIButton isn't the right way to create a button in code.
The way to programatically create a button is:
UIButton * backBtn = [UIButton buttonWithType: UIButtonTypeRoundedRect];
Original attempt:
You need to give your custom back button a proper size. Try doing this before creating the "UIBarButtonItem".
backBtn.frame = CGRectMake(20.0f, 0.0f, 70.0f, 30.0f);
The last number is the height and the second to last number is the button width.

Related

UIBarButtonItem not clickable after changing position

I'm using Xcode 8.0.
I add a custom left barbutton to my NavBar:
UIImage * imageNormal = [UIImage imageNamed:#"InfoIcon"];
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:#selector(testPressed ) forControlEvents:UIControlEventTouchUpInside];
[button setBackgroundImage:imageNormal forState:UIControlStateNormal];
// set the frame of the button
button.frame = CGRectMake(0, 0, imageNormal.size.width, imageNormal.size.height);
UIView * view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, imageNormal.size.width, imageNormal.size.height)];
[view addSubview:button];
// set the barbuttonitem to be the view
UIBarButtonItem * barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:view];
self.navigationItem.leftBarButtonItem = barButtonItem;
Here what I got:
unfortunately my button is not centered because the Nav bar has a custom image higher than the standard. But if I press the info Icon it works.
If I change the icon position with this line of code:
button.frame = CGRectMake(0, -30, imageNormal.size.width, imageNormal.size.height);
I got the right positioning:
But in this case the bar button is not anymore clickable, and I don't get why this is happening.
As workaround I attach a gesture to the view:
UITapGestureRecognizer *_tapOnVideoRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self.revealViewController action:#selector(revealToggle:)];
[view addGestureRecognizer:_tapOnVideoRecognizer];
it works, but the tap is on the view and not on the button so that the changing status of the button when pressed is not working.
#JakubKnejzlik from https://stackoverflow.com/a/12554715/1320479
suggests:
This can be fixed by subclassing the wrapper view (superview of button, custom view of uibarbuttonitem) and overriding the hittest method to return button accordingly.
But I have no idea how to do it

UIBarButtonItem Target Method is not working

Actually i want to place image and label on the toolbar as a UIBarButtonItem and provide a clickable effect to that Button.
So what i have done here is I have created one custom view and placed Image and Label on the same custom view and finally placed this custom view as UIBarButtonItem CustomView.
But when i set target and action for the same UIBarButtonItem, it is not calling the selector method.
The entire code is below.
Can anybody suggest me what's the mistake in my code ? and is there any other approach to achieve the same ????
Early suggestions would be much appreciated.
- (void)viewDidLoad
{
[super viewDidLoad];
[self.navigationController setToolbarHidden:NO];
UIView *customView = [[UIView alloc]
initWithFrame:CGRectMake(0,0,self.navigationController.toolbar.frame.size.width,self.navigationController.toolbar.frame.size.height)];
customView.backgroundColor = [UIColor colorWithRed:62.0/255.0 green:187.0/255.0 blue:150.0/255.0 alpha:1.0];
[self.navigationController.toolbar addSubview:customView];
UIImageView *imgView = [[UIImageView alloc]initWithFrame:CGRectMake(60,0,44,44)];
imgView.image = [UIImage imageNamed:#"documentImage.png"];
[customView addSubview:imgView];
UILabel *lbl = [[UILabel alloc]initWithFrame:CGRectMake(104,0,145,44)];
lbl.text = #"Scan Document";
lbl.textAlignment = NSTextAlignmentLeft;
[customView addSubview:lbl];
UIBarButtonItem *bar = [[UIBarButtonItem alloc]initWithCustomView:customView];
bar.target = self;
bar.action = #selector(scanDocument);
self.toolbarItems = [NSArray arrayWithObjects:bar, nil];
}
If you want to create button right hand side here is the code. i have already implemented it and working fine.
//Button Right side
UIImage *imgFavRest = [UIImage imageNamed:#"documentImage.png"];
UIButton *cart = [UIButton buttonWithType:UIButtonTypeCustom];
[cart setImage:imgFavRest forState:UIControlStateNormal];
cart.frame = CGRectMake(0, 0, imgFavRest.size.width, imgFavRest.size.height);
[cart addTarget:self action:#selector(showCart) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *rightBtn = [[UIBarButtonItem alloc] initWithCustomView:cart];
self.navigationItem.rightBarButtonItem = rightBtn;
Then use method like this . that's all
-(void)cartItemCount{
// Method
}
float textwidth = 50; // according to your text
UIImage *image = [UIImage imageNamed:#"logout"];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.bounds = CGRectMake( 10, 0, image.size.width+textwidth, image.size.height );
[btn addTarget:self action:#selector(scanDocument) forControlEvents:UIControlEventTouchUpInside];
[btn setImage:image forState:UIControlStateNormal];
[btn setTitle:#"test" forState:UIControlStateNormal];
[btn setTitleEdgeInsets:UIEdgeInsetsMake(0.0, 5.0, 0.0, 0.0)];
//Adjust the coordinates and size of your button as your requirement.This is a sample code to guide you.
//PS:Take a UIButton in the nib file>Make it a custom button>Connect the IBOutlet to your custom button in the nib file.Thats it.
UIBarButtonItem *rightButton = [[UIBarButtonItem alloc] initWithCustomView:btn];
self.navigationItem.rightBarButtonItem = rightButton;
I see very complicated answers, all of them using code. However, if you are using Interface Builder, there is a very easy way to do this:
Select the button and set a title and an image. Note that if you set
the background instead of the image then the image will be resized if
it is smaller than the button.IB basic image and title
Set the position of both items by changing the edge and insets. You
could even control the alignment of both in the Control section.
IB position set IB Control set
You could even use the same approach by code, without creating UILabels and UIImages inside as other solutions proposed. Always Keep It Simple!
EDIT: Attached a small example having the 3 things set (title, image and background) with correct insets Button preview
Note:: UIBarButtonItem inherits from UIBarItem and NSObject so it doesn't know anything about touches. It would be nice if the docs mentioned that the action and target properties only apply if the custom view is a UIButton.

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.

UIBarButtonItem with UIButton as custom view doesn't show up

I am trying to display a custom UIButton as a UINavigationItem's rightBarButtonItem.
I wrote the following code:
UIButton *inviteButton = [UIButton buttonWithType:UIButtonTypeCustom];
[inviteButton setTitle:#"Invite" forState:UIControlStateNormal];
inviteButton.frame = CGRectMake(0, 0, 30, 30);
inviteButton.backgroundColor = [UIColor redColor];
inviteButton.layer.borderColor = [UIColor blueColor].CGColor;
inviteButton.layer.borderWidth = 1.0f;
UIBarButtonItem *inviteButtonContainer = [[UIBarButtonItem alloc] initWithCustomView:inviteButton];
viewController.navigationItem.rightBarButtonItem = inviteButtonContainer;
Nothing shows up in my navigation bar.
However, with the following code, I can see a basic button:
UIBarButtonItem *inviteButton = [[UIBarButtonItem alloc] initWithTitle:#"Invite"
style:UIBarButtonItemStyleDone
target:self
action:nil];
viewController.navigationItem.rightBarButtonItem = inviteButton;
But it's obviously not what I am after, since I am looking to play with the button appearance.
Edit
I was trying to add the same instance of UIBarButtonItem (inviteButtonContainer) to many navigation bars. Doing that, it's visible on the last navigation bar only.
However, if I use the same instance of a simple UIBarButtonItem (without custom view), it's displayed on every navigation bars. Any idea why?
Your code is fine, just change this line:
viewController.navigationItem.rightBarButtonItem = inviteButtonContainer;
to
self.navigationItem.rightBarButtonItem = inviteButtonContainer;
From the Documentation:
The navigation item used to represent the view controller in a
parent's navigation bar.
self itself represents that it belongs to view controller , so there is no need to mention the view controller instance to add the navigation item.
-> To display custom button in a view controller in which custom bar button is crated (i.e. in self) :
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *inviteButton = [UIButton buttonWithType:UIButtonTypeCustom];
[inviteButton setTitle:#"Invite" forState:UIControlStateNormal];
inviteButton.frame = CGRectMake(0, 0, 70, 30);
inviteButton.backgroundColor = [UIColor redColor];
inviteButton.layer.borderColor = [UIColor blueColor].CGColor;
inviteButton.layer.borderWidth = 1.0f;
UIBarButtonItem *inviteButtonContainer = [[UIBarButtonItem alloc] initWithCustomView:inviteButton];
controller.navigationItem.rightBarButtonItem = inviteButtonContainer;
}
-> To display custom bar button in a view controller that is about to present
eg. To display a view controller after a cell is selected in table view
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
DjDetailsViewController *controller = (DjDetailsViewController *)
[self.storyboard instantiateViewControllerWithIdentifier:#"DjDetailsViewController"];
UIButton *inviteButton = [UIButton buttonWithType:UIButtonTypeCustom];
[inviteButton setTitle:#"Invite" forState:UIControlStateNormal];
inviteButton.frame = CGRectMake(0, 0, 70, 30);
inviteButton.backgroundColor = [UIColor redColor];
inviteButton.layer.borderColor = [UIColor blueColor].CGColor;
inviteButton.layer.borderWidth = 1.0f;
UIBarButtonItem *inviteButtonContainer = [[UIBarButtonItem alloc] initWithCustomView:inviteButton];
controller.navigationItem.rightBarButtonItem = inviteButtonContainer;
[self.navigationController pushViewController:controller animated:YES];
}
I didn’t done major. I just used your code and change frame of custom bar button.
I hope this will help you.
You issue is with your invite button initialiser:
UIButton *inviteButton = [UIButton UIButtonTypeCustom];
UIButtonTypeCustom is an enum value not a class method/convenience constructor.
use
UIButton *inviteButton = [UIButton buttonWithType:UIButtonTypeCustom];
Hope this helps

how to override the functionality of the navigation bar created by pushViewController

I have a view controller, which is presented using pushViewController. This methods presents the view controller with a navigation bar, with a back button on the left side (this is a cocoa method, created by apple).
I want the back button to do just what it does right now, but I also want to tweak some things with it's animation.
How can I add code which works between the button being pressed and the actual animation and return?
thank you.
I do similar stuff by adding my custom back button like this:
UIImage *backArrow = [UIImage imageNamed:backButtonImage];
UIButton *aBackButton = [UIButton buttonWithType:UIButtonTypeSystem];
CGSize aBackButtonTextSize = [#"Back" sizeWithFont:[UIFont systemFontOfSize:17]];
aBackButton.frame = CGRectMake(0.0, 0.0, aBackButtonTextSize.width + backArrow.size.width, self.navigationController.navigationBar.frame.size.height);
aBackButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
SEL backSelector = NSSelectorFromString(#"backAction");
[aBackButton addTarget:self action:backSelector forControlEvents:UIControlEventTouchUpInside];
[aBackButton setTitle:#"Back" forState:UIControlStateNormal];
[aBackButton setImage:backArrow forState:UIControlStateNormal];
[aBackButton setExclusiveTouch:YES];
aBackButton.titleLabel.font = [UIFont systemFontOfSize:17];
UIBarButtonItem *aLeftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:aBackButton];
UIBarButtonItem *aNegativeSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
aNegativeSpacer.width = -8;
self.navigationItem.leftBarButtonItems = #[aNegativeSpacer, aLeftBarButtonItem];
And then handle user taps and add my own stuff here:
- (void)backAction {
// My own handlings
}

Resources