UIButtonBarItem looks wrong - ios

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...)

Related

iOS - What is the proper way to just display back button and no navigationBar?

Above design can be achieve using setNavigationBarHidden = YES and by adding UIButton at the top for backButton behavior. But I wanna avoid this hack/method.
Is it possible I can still use leftBarButtonItems for backButton without navigationBar ?
What is the recommended and proper approach for this kind of design ?
leftBarButtonItems is the property of UINavigation item , so you can not use it without navigationbar. So probably if you dont want to use navigationbar adding custom button is way to go.
leftBarButtonItems is an accessory which is only used with navigation bar, if you want to use that you will only use it with navigation bar.
Now if you dont want to add the custom button, then just make the UINavigationBar transparent using the below code.
[self.navigationBar setBackgroundImage:[UIImage new]
forBarMetrics:UIBarMetricsDefault];
self.navigationBar.shadowImage = [UIImage new];
self.navigationBar.translucent = YES;
You can do this without even hiding the navigation bar like
UIButton *backBtn = [[UIButton alloc] initWithFrame:CGRectMake(10, 5, 60, 20)];
[backBtn setImage:[UIImage imageNamed:#"navigationBar_back_image"] forState:UIControlStateNormal]; // use your image or setText of backBtn "<"
[backBtn addTarget:self action:#selector(pushBackBtnTpd:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backBtn] ;
self.navigationItem.leftBarButtonItem = backBarButtonItem;
-(IBAction)pushBackBtnTpd:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}

Possible to have iOS Navigation Bar Button Item disabled and highlighted?

Is it possible to have a UIBarButtonItem that is disabled (non-interactive) as well as highlighted. My desire is to have a status icon in the NavBar, so I want it to be highlighted (not gray), but at the same time I don't want it to be a button. Can you add things besides UIBarButtonItems to a NavBar?
Thanks!
Sure you can!
Besides the name, UIBarButtonItem is not necessarily a button. You can add an image or anything else you want.
There's a initWithCustomView constructor where you can pass any view as parameter. For example:
UIImageView *statusImageView = [[UIImageView alloc] initWithImage: [UIImage imageNamed: #"status"]];
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithCustomView: statusImageView];
If you want a clickable status, you can put the ImageView inside the UIButton.

Adding action and target to a custom Navigation BarButtonItem?

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");
}

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 Button initWithImage displaying a default button behind the custom image

I am trying to make a button for my navigation bar with a custom image. When I run the following code, the button appears as it should, except you can see another wider button behind it, sticking out the sides. How do I get rid of that other button?
UIBarButtonItem *emailButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"emailBut"]
style:UIBarButtonSystemItemCompose
target:self
action:#selector(emailSheet)];
self.navigationItem.rightBarButtonItem = emailButton;
Hmm... UIBarButtonSystemItemCompose is a system icon, so I guess you are probably overlaying your icon on top of it. You should instead use UIBarButtonItemStylePlain (or other styles) for your style: argument.
Edit:
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(...)];
[button setBackgroundImage:someImage];
[button addTarget:self action:#selector(something:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
[self.navigationItem setRightBarButtonItem:barButtonItem];
Ok, for some reason initWithImage only puts the image in the center of a default button. The fix was to initWithCustomView as iBlue suggested.
Another thing to note is that the barBackButton doesn't allow custom views, so I had to make that one a leftButton instead of a backButton, with my own go back method. I hope Apple makes this easier in the future.

Resources