Adding action and target to a custom Navigation BarButtonItem? - ios

I am trying to customize the Navigation Bar by adding a custom button to the rightBarButtonItem. Creating one is pretty straight forward.
UIImage *myImage = [UIImage imageNamed:#"menu-icon.png"];
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myButton setFrame:CGRectMake(0, 0, myImage.size.width, myImage.size.height)];
[myButton setBackgroundImage:myImage forState:UIControlStateNormal];
UIBarButtonItem *myButtonItem = [[UIBarButtonItem alloc] initWithCustomView:myButton];
[navItem setLeftBarButtonItem:myButtonItem animated:YES];
Looks good, except that now I can't set the target or action properties. The following code does nothing:
myButtonItem.target = myTarget;
myButtonItem.action = #selector(myButtonAction);
I found that the reason it's not working is because I initialized the UIBarButtonItem with -initWithCustomView. Apples documentation says:
The bar button item created by this method does not call the action method of its target in response to user interactions. Instead, the bar button item expects the specified custom view to handle any user interactions and provide an appropriate response.
I'm a little confused by what exactly apple means by that. Am I supposed to create a custom control or something? I haven't really done that yet and I'm not sure where to start.
Does anyone have any suggestions on how to do this or an alternative way to set up a custom Navigation Bar Button?
ANSWERED----------------------------------------------------------
Just had to add this method to the UIButton:
[myButton addTarget:myTarget action:#selector(myButtonAction) forControlEvents:UIControlEventTouchUpInside];

It's pretty straight forward, you need to add target for uibutton not for uibarbuttonitem.
To explain more what you want for uibarbuttonitem is respond touch up inside action method, as documentation says that you need to do that for uibutton as you are initializing your uibarbuttonitem with custom view in your case uibutton.

Add an action and target to a UIButton like this:
[myButton addTarget:self
action:#selector(handleMyButtonTap)
forControlEvents:UIControlEventTouchUpInside];
Add an action and target to a UIBarButtonItem like this:
[myBarButtonItem setAction:#selector(handleBarButtonTap)];
[myBarButtonItem setTarget:aTarget];

With the help of answers by hgwhittle and Mustafa I implemented and it works perfect
here is the complete snip may help someone
//Create ImageButton
UIImage *shareBtnIcon = [UIImage imageNamed:#"dummy_share_icon_22"];
UIButton *shareButton = [UIButton buttonWithType:UIButtonTypeCustom];
[shareButton setFrame:CGRectMake(0, 0, shareBtnIcon.size.width, shareBtnIcon.size.height)];
[shareButton setBackgroundImage:shareBtnIcon forState:UIControlStateNormal];
[shareButton addTarget:self action:#selector(shareButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
//Create BarButton using ImageButton
UIBarButtonItem *shareBarBtn = [[UIBarButtonItem alloc] initWithCustomView:shareButton];
//Add BarButton to NavigationBar
self.navigationItem.rightBarButtonItems = [[NSArray alloc] initWithObjects:shareBarBtn, nil];
//method for share butto click
-(void) shareButtonClicked:(UIButton*)sender
{
NSLog(#"you clicked on share button %ld");
}

Related

Custom navigation bar not showing

Controller 1 displays an array of UIImages, Controller 2 manages the paging of those images once selected, and Controller 3 just displays the images for the pages. When I tap on a cell and load a photo into the photoViewController, the paging of images works fine, but my custom navigation bar is overridden with the default bar and I am unable to add any custom buttons to it or change any of its properties in code. The only thing I found that I am able to do is hide it. If I try to change the title of the back button or add my own title to the navigation bar nothing changes. Please help with anything you can.
i think you should try like this
self.navigationItem.leftBarButtonItem = [self leftMenuBarButtonItem];
and function could be
- (UIBarButtonItem *)leftMenuBarButtonItem {
UIButton *backButton = [[UIButton alloc] initWithFrame:CGRectMake(50, 50, 50, 30)]; [backButton setImage:[UIImage imageNamed:#"bar_btn_bg.png"] forState:UIControlStateNormal];
[backButton addTarget:self action:#selector(leftDrawerButtonPress:) forControlEvents:UIControlEventTouchUpInside];
return [[UIBarButtonItem alloc] initWithCustomView:backButton];
}
if you fall in between let me know

Intercept back navigation in iOS7

I want to stop somebody going back on my Navigation Controller if they haven't saved their changes. Most posts on SO discuss overriding the back button (with a variety of techniques to do this). However, iOS7 allows you to now swipe to go back in a navigationViewController...
I did see the UINavigationControllerDelegate which looks like the right type of delegate I'd want to implement but I see no way to cancel a navigation action. Any ideas how to do this?
Unfortunately nothing changed in iOS7, you still need to fake your back button if you want to put some check into it.
By the way it easier now since you don't need to fake the arrow button.
Edit:
to do that:
UIButton *backButton = [[UIButton alloc] initWithFrame: CGRectMake(0, 0, 44.0f, 30.0f)];
[backButton setImage:[UIImage imageNamed:#"back.png"] forState:UIControlStateNormal];
[backButton addTarget:self action:#selector(popVC) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];

UIButtonBarItem looks wrong

I think this is going to be a stupid question, but I can't seem to find the answer. I have a few simple lines of code to put a button in the navigation bar:
UIBarButtonItem *cancelButton=[[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:#"button-cancel.png"] style:UIBarButtonItemStylePlain target:self action:#selector(cancelPressed:)];
UINavigationItem *item = [[UINavigationItem alloc] init];
item.leftBarButtonItem = cancelButton;
item.hidesBackButton = YES;
[self.navigationBar pushNavigationItem:item animated:NO];
This button works fine, but it looks like this:
Any thoughts?
You probably want to create the bar button item using a custom view, where the custom view is a UIButton:
UIImage *cancelImage = [UIImage imageNamed:#"button-cancel"];
UIButton *cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
cancelButton.frame = (CGRect){CGPointZero, cancelImage.size);
[cancelButton setImage:cancelImage forState:UIControlStateNormal];
UIBarButtonItem *cancelBarButton = [[UIBarButtonItem alloc] initWithCustomView:cancelButton];
Set your button (cancelButton) size according to the size of the button-cancel.png.
stopButton.frame = CGRectMake ();
Instead, create a custom type UIButton with your image. Set the target and selector of the UIbutton to what you wish the bar button item to do. Then initialize the bar button item as follows:
UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
Where button is your UIButton using the desired image.
UIBarButtonItem/initWithImage: is typically used for making iconic buttons - not buttons that have text in them.
If you just want to change how the common textual UIBarButtonItem looks, you just need to set the background image of your bar button item. This way you don't have to have images for each button that contain your button text.
Docs: - (void)setBackgroundImage:(UIImage *)backgroundImage forState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics
You can also set this app-wide by calling setBackgroundImage: on the UIBarButtonItem appearance proxy.
Lastly, note that you'll likely need to create a resizeable image to pass to setBackgroundImage. This will let your single image accomodate any button size. See UIImage/resizeableImageWithCapInsets:resizingMode: (iOS6) or UIImage/stretchableImageWithLeftCapWidth:topCapHeight: (pre iOS6)
You can certainly do what #Wain suggests but there are drawbacks. For one, your press-handler will no longer be sending a UIBarButtonItem as the 'sender'. That may not seem like much until you have a common handler that suddenly needs to determine if the sender is a UIBarButtonItem or a UIButton, or if you want to present a UIPopoverController against this BarButtonItem (but you only have the UIButton reference...)

Custom UIBarButtonItem back button

I need to customize UIBarButtonItem back button so it is displayed with a simple arrow icon (like in Facebook, Twitter etc). Do I need to create a custom UIBarButtonItem and manually add it to the nav bar or is there a way to do this through appearance API?
Thanks
You have to make your own and add it
You can do it like this (this is for a custom button using an image)
UIImage* image3 = [UIImage imageNamed:#"favorites.png"];
CGRect frameimg = CGRectMake(0, 0, image3.size.width, image3.size.height);
UIButton *someButton2 = [[UIButton alloc] initWithFrame:frameimg];
[someButton2 setBackgroundImage:image3 forState:UIControlStateNormal];
[someButton2 addTarget:self action:#selector(loadFavorites)
forControlEvents:UIControlEventTouchUpInside];
[someButton2 setShowsTouchWhenHighlighted:YES];
UIBarButtonItem *favoritesButton =[[UIBarButtonItem alloc] initWithCustomView:someButton2];
self.navigationItem.rightBarButtonItems =[NSArray arrayWithObjects:favoritesButton, nil];
Okay so it turns out that you can't actually use backBarButtonItem with a UIBarButtonItem created with a custom view. The best I can offer is you can create a template with an image and a empty background image, although it feels a bit like spacer.gif. I threw together a quick example to show what I meant about the view controller ordering too.
http://cl.ly/36091p0l0120

Custom UIButton to drill up from table view?

Ive put in a custom "Back" UIBarButtonItem, which is from an Image i made in photoshop. Ive managed to make it appear just fine, my problem is making it work.
My button does nothing, im assuming because i havent assigned any actions to it. I just dont know the correct syntax to do so?
Heres my code
UIImage *buttonImage = [UIImage imageNamed:#"BackButton.png"];
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
[backButton setBackgroundImage:buttonImage forState:UIControlStateNormal];
backButton.frame = CGRectMake(0, 0, buttonImage.size.width, buttonImage.size.height);
// Im assuming this is where i need to put the action...
//[backButton addTarget:self action:#selector(.......) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]
initWithCustomView:backButton];
Basically, i want my new custom backbutton to function just like the default one in a regular UITableView
regards,
Andyy
You can do this in IB or you can do it in code with a call to addTarget:action:forControlEvents: for UIControlEventTouchUpInside to invoke a method (action) when the button is tapped. For example:
[backButton addTarget:self action:#selector(backButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
This is documented in UIControl class reference, UIButton is a subclass of UIControl.
You'll need a method which will be called when the event occurs, which I called backButtonPressed: in my code above. This method takes one parameter, the object sending the event, something like this:
-(void)backButtonPressed:(id)sender
{
// NOTE: assumes self is your UIViewController
[self.navigationController popViewControllerAnimated:YES];
}

Resources