Custom Button initWithImage displaying a default button behind the custom image - ios

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.

Related

ios hide text of left navigation button

I need to show only arrow button and hide text of left navigation button. According to this link, I can do like this. But if I do like that, slide to go back feature will be destroyed.
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"" style:UIBarButtonItemStylePlain target:nil action:nil];
So, I use like this to hide text.
self.navigationController.navigationBar.topItem.title = #"";
So far, it is okay. However, if my previous view's searchDisplayController is active and push to new view,it show left navigation button text. May I know how to do?
Copy and paste this line in every view controller:
self.navigationController.navigationItem.leftBarButtonItem.title = " "
Alternatively you can achieve this in storyboard/xib files using the following steps:-
Drag and drop a Navigation Item from object library onto your ViewController. Then select the ViewController.
Select that Navigation Item in the menu on left side(it will the one with back arrow and Title as text: "< Title").
Select Attribute Inspector on the right hand side and replace text: Title with an empty space.
Repeat these steps for all the the view controllers.
Hope it helps.
One solution you will have to add custom button for your requirement like this:
//create image instance add here back image
UIImage *imgBack = [UIImage imageNamed:#"image name here"];
//create UIButton instance for UIBarButtonItem
UIButton *btnBack = [UIButton buttonWithType:UIButtonTypeCustom];
[btnBack setImage:imgBack forState:UIControlStateNormal];
btnBack.frame = CGRectMake(0, 0, imgBack.size.width,imgBack.size.height);
[btnBack addTarget:self action:#selector(btnBackAction:) forControlEvents:UIControlEventTouchUpInside];
//create UIBarButtonItem instance
UIBarButtonItem *barBtnBackItem = [[UIBarButtonItem alloc] initWithCustomView:btnBack];
//set in UINavigationItem
self.navigationItem.leftBarButtonItem = barBtnBackItem;
Button method given below:
-(void)btnBackAction:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
EDIT : For slide swipe add in viewDidLoad method
//for enabling swipe gesture
if ([self.navigationController respondsToSelector:#selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled = YES;
}
#Atif's answer is correct. I just want to add in that, instead of copying and pasting the code in all files, create a custom UINavigationController and implement the required code as mentioned by #Atif.(I cannot comment due to low rating.)

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

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

How do I specify an action for a custom Back button in a standalone UINavigationBar?

I have a custom UINavigationBar on a screen, i.e., no navigation controller, as defined below which contains a Back button w/ the title "Media" and the action "mediaViewComplete". However, the mediaViewComplete method is not being called when the button is tapped. How do you specify an action for a Back button?
self.navigationBar=[[UINavigationBar alloc]initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 44)];
navigationBar.barStyle=UIBarStyleBlackTranslucent;
UINavigationItem *navigationItem=[[UINavigationItem alloc]init];
UIBarButtonItem *backButton=[[UIBarButtonItem alloc]initWithTitle:#"Media" style:UIBarButtonItemStylePlain target:self action:#selector(mediaViewComplete)];
navigationItem.backBarButtonItem=backButton;
[self.navigationBar pushNavigationItem:navigationItem animated:NO];
navigationItem=[[UINavigationItem alloc]init];
UIBarButtonItem *editButton=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:#selector(editCategorization)];
navigationItem.rightBarButtonItem=editButton;
[self.navigationBar pushNavigationItem:navigationItem animated:NO];
[self.view addSubview:navigationBar];
[editButton release];
[backButton release];
[navigationItem release];
The problem is that you are using:
navigationItem.backBarButtonItem = backbutton;
The backBarButtonItem has it's own event that is not overridden by your action: option. In fact, Apple guidelines state that you should use "nil" as you action for backBarButtonItem. The backBarButtonItem is not owned by the current view controller.
If you are unconcerned about the arrow shape of the button, you should use leftBarButtonItem instead. If you want to create fully custom back buttons with the arrow shape, you'll have to do some custom magic. Luckily, most of the work has been done for you:
http://idevrecipes.com/2011/01/12/how-do-iphone-apps-instagramreederdailybooth-implement-custom-navigationbar-with-variable-width-back-buttons/
Download this project and look at the results. It even contains the images you need to retain an arrow shaped custom back button. It is more work, but it's much less hack.

Resources