Can't adjust spacing of UIBarButtonItem(s) when assigned to navigationItem.rightBarButtonItems - iphone

This is a weird problem.
The situation is that I want to adjust the spacing between my UIBarButtonItem(s) so that they are just 2 pixels apart.
I am able to do this quite easily with UIToolbar:
// Make bottom button bar buttons
NSMutableArray *bottomButtons = [[NSMutableArray alloc] initWithCapacity:3];
// Create spacer between buttons
UIBarButtonItem *spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
[bottomButtons addObject:spacer];
UIBarButtonItem* noSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
noSpace.width = -10;
// Add button 1
self.addAlbumButton = [UIGlossyButton buttonWithType:UIButtonTypeCustom];
[self.addAlbumButton setTitle:#"Button 1" forState:UIControlStateNormal];
[self.addAlbumButton addTarget:self action:#selector(addAlbum:) forControlEvents:UIControlEventTouchUpInside];
self.addAlbumBarButton = [[UIBarButtonItem alloc] initWithCustomView:self.addAlbumButton];
[bottomButtons addObject:self.addAlbumBarButton];
[bottomButtons addObject:noSpace];
// Add button2
self.downloadAllItemsButton = [UIGlossyButton buttonWithType:UIButtonTypeCustom];
[self.downloadAllItemsButton setTitle:#"Button 2" forState:UIControlStateNormal];
[self.downloadAllItemsButton addTarget:self action:#selector(downloadAllItemsAction:) forControlEvents:UIControlEventTouchUpInside];
self.downloadAllItemsBarButton = [[UIBarButtonItem alloc] initWithCustomView:self.downloadAllItemsButton];
[bottomButtons addObject:self.downloadAllItemsBarButton];
// add all button to bottom toolbar
[self.bottomToolbar setItems:bottomButtons];
The problem is when I try to do this with the navigationbar. For some reason, when I insert a fixed length button (with a negative value), it won't shrink the space between the buttons. I know the fixed length button is there and working because if I change the width to a positive number, the spacing between the buttons increases.
The code is basically the same except that instead of adding the buttons to self.bottomToolbar, I'm calling the following code:
self.navigationItem.rightBarButtonItems = bottomButtons;
I have found the same issue with the MasterViewController. I'm using a splitviewcontroller and the bottom toolbar works fine but the top toolbar has the same spacing problem. That problem, is I can't make the space between buttons less than the default.
It seems like navigationItem.rightBarButtonItems works differently than all other toolbars.

after adding all navigationButtonItem in to an array you can do it like the following way. i guess this will help you also coz this works for me and if you want to change space between button you can change it with help of macro
#define ONE_BUTTON_WIDTH 30.0f
#define SPACE_BETWEEN_BUTTONS 12.0f
#define ONE_BUTTON_TOTAL_WIDTH (ONE_BUTTON_WIDTH + SPACE_BETWEEN_BUTTONS)
#define kBookmarksImage [UIImage imageNamed:#"bookmarks.png"]
/* CREATE BOOKMARKS BUTTON */
UIButton *bookmarksButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, kBookmarksImage.size.width, kBookmarksImage.size.height)];
[bookmarksButton setImage:kBookmarksImage forState:UIControlStateNormal];
[bookmarksButton addTarget:target action:#selector(toolbarButtonTapped:) forControlEvents:UIControlEventTouchDown];
bookmarksButton.tag = kBookmarksButtonTag;
UIBarButtonItem *bookmarksButtonItem = [[UIBarButtonItem alloc] initWithCustomView:bookmarksButton];
UIBarButtonItem *spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
spacer.width = SPACE_BETWEEN_BUTTONS;
[buttons addObjectsFromArray:#[bookmarksButtonItem,spacer]];
/* ADD ALL THESE BUTTONS TO CUSTOM TOOLBAR AND TOOLBAR TO NAVIGATION BAR */
UIToolbar *customToolbar = [[UIToolbar alloc]
initWithFrame:CGRectMake(0.0f, 0.0f, ([bottomButtons count]/2*ONE_BUTTON_TOTAL_WIDTH), 44.01f)]; // 44.01 shifts it up 1px for some reason
customToolbar.clearsContextBeforeDrawing = NO;
customToolbar.clipsToBounds = NO;
customToolbar.tintColor = [UIColor colorWithWhite:0.305f alpha:0.0f]; // closest I could get by eye to black, translucent style.
customToolbar.barStyle = -1; // clear background
[customToolbar setItems: bottomButtons animated:NO];
UIBarButtonItem *customUIBarButtonitem = [[UIBarButtonItem alloc] initWithCustomView:customToolbar];
self.navigationItem.rightBarButtonItem = customUIBarButtonitem;

Easiest way just create a method to set up UIButton for each UIBarButtonItem like so:
- (UIBarButtonItem*)createAddAlbumBarButtonWithImage:(NSString*)imageName
{
UIButton* button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
[button setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
[button addTarget:self action:#selector(addAlbum:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem* barButton = [[UIBarButtonItem alloc] initWithCustomView:button];
return barButton;
}

Related

UIToolBar item coordinates

My problem is following: i want to know the coordinates to an item of a toolbar so that i could pop some data right there. These barbuttonitems never reveal me there frame properties.
Is there a solution?
You can use if you want to give spacing.
UIBarButtonItem *fixedLeftSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:self action:nil];
// for adding Custom view
UIButton *webButton = [UIButton buttonWithType:UIButtonTypeCustom];
[webButton setFrame:CGRectMake(0, 0, 50, 40)];
[webButton setImage:[UIImage imageNamed:#\"webIcon.jpg\"] forState:UIControlStateNormal];
[webButton addTarget:self action:#selector(goToWebPage) forControlEvents:UIControlEventTouchDown];
UIBarButtonItem *webpageBtn = [[UIBarButtonItem alloc]initWithCustomView:webButton];
[webpageBtn setTarget:self];
[webpageBtn setAction:#selector(goToWebPage)];
[toolbar setItems:[NSArray arrayWithObjects: webpageBtn,fixedLeftSpace,webpageBtn, nil]];
Also see the link.
UIToolbar* tools = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 210, 44)];
UIBarButtonItem *space = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
NSMutableArray* buttons = [[NSMutableArray alloc] initWithObjects:bt1,space,bt2,space,bt3, nil];
[tools setItems:buttons animated:YES];
UIBarButtonItem *toolsBtn = [[UIBarButtonItem alloc]initWithCustomView:tools];
self.navigationItem.rightBarButtonItem = toolsBtn;
If you are creating a toolbar from xib file then you need to add multiple "flexible space bar button item" before and after the buttons if you multiple bar buttons on toolbar until you get the desired spacing.
If you are creating UIToolbar dynamically then you need to add flexible buttons dynamically.

Add bar button in UINavigationbar

I am new to iPhone developer,
I want to add one more button next to the Back button on my navigation bar, i am using navigation controller so back button is already there on left side. and on extreme right side i have added one button using
self.navigationItem.rightBarButtonItem = ModeButton;
but when i write,
self.navigationItem.leftBarButtonItem = NewButton;
NewButton overrides my back button, i want to place my new button next to back button.
Any help will be appreciated.
UINavigationItem has a property leftItemsSupplementBackButton, you can use it.
leftItemsSupplementBackButton
A Boolean value indicating whether the left items are displayed in addition to the back button.
#property BOOL leftItemsSupplementBackButton
Discussion
Normally, the presence of custom left bar button items causes the back button to be removed in favor of the custom items. Setting this property to YES causes the items in the leftBarButtonItems or leftBarButtonItem property to be displayed to the right of the back button—that is, they are displayed in addition to, and not instead of, the back button. When set to NO, the items in those properties are displayed instead of the back button. The default value of this property is NO.
From UINavigationController Class Reference.
UIBarButtonItem *leftBarButtonItem =[[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(logout)];
self.navigationItem.leftBarButtonItem = leftBarButtonItem;
self.navigationItem.leftItemsSupplementBackButton = YES;
I think you should a flexible space for it to not overlap other, maybe something like this should get you started.
UIBarButtonItem *back = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStyleBordered target:self action:#selector(Back:)];
UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *newButton = [[UIBarButtonItem alloc] initWithTitle:#"newButton" style:UIBarButtonItemStyleBordered target:self action:#selector(newButtonMethod:)];
NSArray *navBarItems = [[NSArray alloc] initWithObjects:back, flexibleSpace, newButton, nil];
EDIT:
NSMutableArray* buttons = [[NSMutableArray alloc] initWithCapacity:3];
UIBarButtonItem *back = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStyleBordered target:self action:#selector(Back:)];
[buttons addObject:back];
    UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
[buttons addObject:flexibleSpace];
    UIBarButtonItem *newButton = [[UIBarButtonItem alloc] initWithTitle:#"newButton" style:UIBarButtonItemStyleBordered target:self action:#selector(newButtonMethod:)];
[buttons addObject:newButton];
UIToolbar* myToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 100, 45)];
        [myToolbar setTintColor:[self.navigationController.navigationBar tintColor]];
[myToolbar setItems:buttons animated:NO];
UIBarButtonItem *myButton = [[UIBarButtonItem alloc] initWithCustomView:myToolbar];
self.navigationItem.leftBarButtonItem = myButton;
Create one custom view which will contain two buttons, then create bar button item as follows:
UIBarButtonItem *leftBarButtonItem =[[UIBarButtonItem alloc] initWithCustomView:userCustomView];
self.navigationItem.leftBarButtonItem = leftBarButtonItem;
Edit:
Below code is just an example of how you create two buttons,
UIView *customView = [[UIView alloc] init];
customView.frame = CGRectMake(0, 0, 100, 40);
UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button1 setTitle:#"Add" forState:UIControlStateNormal];
button1.frame = CGRectMake(0, 0, 50, 40);
UIButton *button2 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button2 setTitle:#"del" forState:UIControlStateNormal];
button2.frame = CGRectMake(60, 0, 50, 40);
[customView addSubview:button2];
[customView addSubview:button1];
UIBarButtonItem *barItem =[[UIBarButtonItem alloc] initWithCustomView:customView];
self.navigationItem.leftBarButtonItem = barItem;
For achieving this, you will have to make a Custom UIBarButtonItem. Ans in that you will have to put both the buttons, BackButton (User Defined) and NewButton respectively like this:
UIView *viewForLeftBarButton = [[UIView alloc] initWithFrame:CGRectMake(5, 5, 100, 35)];
[viewForLeftBarButton addSubview:BackButton];
[viewForLeftBarButton addSubview:NewButton];
UIBarButtonItem *leftBarButtonItem =[[UIBarButtonItem alloc] initWithCustomView:viewForLeftBarButton];
self.navigationItem.leftBarButtonItem = leftBarButtonItem;

why images not coming for UIBarButton item of navigation Bar

Here is my code. This is adding image but images are being appeared in navigation bar.
UIToolbar* toolbartop = [[UIToolbar alloc]
initWithFrame:CGRectMake(0, 0, 100, 45)];
[toolbar setBarStyle: UIBarStyleBlackOpaque];
// create an array for the buttons
NSMutableArray* buttonstop = [[NSMutableArray alloc] initWithCapacity:5];
UIBarButtonItem *remainderButton = [[UIBarButtonItem alloc]
initWithImage:[UIImage imageNamed:#"home.png"]
style:UIBarButtonItemStylePlain
target:self
action:#selector(LoadOption:)];
[buttonstop addObject:remainderButton];
[remainderButton release];
UIBarButtonItem *faveButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"home.png"]
style:UIBarButtonItemStylePlain
target:self
action:#selector(homeAction)];
[buttonstop addObject:faveButton];
[faveButton release];
// put the buttons in the toolbar and release them
[toolbartop setItems:buttonstop animated:NO];
[buttonstop release];
// place the toolbar into the navigation bar
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:toolbartop];
But this code is showing image in navigation right bar.
UIBarButtonItem *settingButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"home.png"]
style:UIBarButtonItemStylePlain
target:self
action:#selector(homeAction)];
self.navigationItem.rightBarButtonItem = settingButton;
Why left navigation bar button is not showing images?
[toolbartop release];
You can add the image to your left BarButtonItem as follows:
UIButton *button1 = [[UIButton alloc] init];
button1.frame=CGRectMake(0,0,105,30);
[button1 setBackgroundImage:[UIImage imageNamed: #"image1.png"] forState:UIControlStateNormal];
[button1 addTarget:appDelegate action:#selector(Open_Link1) forControlEvents:UIControlEventTouchUpInside];
UIButton *button2 = [[UIButton alloc] init];
button2.frame=CGRectMake(105,0,105,30);
[button2 setBackgroundImage:[UIImage imageNamed: #"image2.png"] forState:UIControlStateNormal];
[button2 addTarget:appDelegate action:#selector(Open_Link2) forControlEvents:UIControlEventTouchUpInside];
UIView *viewButtons = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 210, 30)];
[viewButtons addSubview:button1];
[viewButtons addSubview:button2];
[button1 release];
[button2 release];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:viewButtons];
[viewButtons release];
Here please make sure that the methods "Open_Link1" and "Open_Link2" must exists in the code as follows:
-(void)Open_Link1
{
// Write your logic
}
-(void)Open_Link2
{
// Write your logic
}
Let me know if you want more help.
The left bar button item is automatically used by the framework for showing a "Back" button. You can't put anything here, at least not when your navigation bar is managed by a UINavigationController. For this to work you have to handle the UINavigationBar yourself.
Edit:
in your leftBarButtonItem, try putting a UISegmentedControl instead of a UIToolbar for toolbartop.
You are adding a button to toolbar but you aren't adding your toolbar to any view. Try to set the button directly using
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:buttonStop];

Multiple UIBarButtonItems in UINavigationBar

How to Create multiple bar button in navigation bar?
From iOS 5 onwards, you can now do it using setLeftBarButtonItems:animated: or setRightBarButtonItems:animated:
You must use UIToolbar and set the toolbar with buttons:
// create a toolbar where we can place some buttons
UIToolbar *toolbar = [[UIToolbar alloc]
initWithFrame:CGRectMake(0, 0, 100, 45)];
[toolbar setBarStyle: UIBarStyleBlackOpaque];
// create an array for the buttons
NSMutableArray *buttons = [[NSMutableArray alloc] initWithCapacity:3];
// create a standard save button
UIBarButtonItem *saveButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemSave
target:self
action:#selector(saveAction:)];
saveButton.style = UIBarButtonItemStyleBordered;
[buttons addObject:saveButton];
// create a spacer between the buttons
UIBarButtonItem *spacer = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil
action:nil];
[buttons addObject:spacer];
// create a standard delete button with the trash icon
UIBarButtonItem *deleteButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemTrash
target:self
action:#selector(deleteAction:)];
deleteButton.style = UIBarButtonItemStyleBordered;
[buttons addObject:deleteButton];
// put the buttons in the toolbar and release them
[toolbar setItems:buttons animated:NO];
// place the toolbar into the navigation bar
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]
initWithCustomView:toolbar];
you have to create a view with as much button you required and have to add them on navigation button like following :
UIView *parentView1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 60, 44)];
UIButton *infoButton1 = [[UIButton alloc] initWithFrame:CGRectMake(0, 6, 30, 32)];
[infoButton1 setBackgroundImage:[UIImage imageNamed: #"navbtn.png"] forState:UIControlStateNormal];
[infoButton1 setTitle:#"Back" forState:UIControlStateNormal];
infoButton1.titleLabel.font = [UIFont systemFontOfSize:13.0f];
infoButton1.titleLabel.textColor = [UIColor whiteColor];
[infoButton1 addTarget:self action:#selector(backBarButtonClicked) forControlEvents:UIControlEventTouchUpInside];
[parentView1 addSubview:infoButton1];
[infoButton1 release];
UIButton *infoButton2 = [[UIButton alloc] initWithFrame:CGRectMake(30, 6, 30, 32)];
[infoButton2 setBackgroundImage:[UIImage imageNamed: #"navbtn.png"] forState:UIControlStateNormal];
[infoButton2 setTitle:#"Back" forState:UIControlStateNormal];
infoButton2.titleLabel.font = [UIFont systemFontOfSize:13.0f];
infoButton2.titleLabel.textColor = [UIColor whiteColor];
[infoButton2 addTarget:self action:#selector(backBarButtonClicked) forControlEvents:UIControlEventTouchUpInside];
[parentView1 addSubview:infoButton2];
[infoButton2 release];
UIBarButtonItem *customBarButtomItem1 = [[UIBarButtonItem alloc] initWithCustomView:parentView1];
[parentView1 release];
self.navigationItem.leftBarButtonItem = customBarButtomItem1;
[customBarButtomItem1 release];`enter code here`
I know this question was already closed, but I find that the UIToolbar solution doesn't match visually.
If you instead use a second UINavigationBar set with a UINavigationItem that has a title of nil and the desired buttons you can add more buttons and have a bar that visually matches the original.
For iOS7 and higher, this is the right way to do it. No need for UIToolbar silliness.
- (void)viewDidLoad {
[super viewDidLoad];
[self configureView];
// create three funky nav bar buttons
UIBarButtonItem *one = [[UIBarButtonItem alloc]initWithTitle:#"One" style:UIBarButtonItemStylePlain target:self action:#selector(testMethod)];
UIBarButtonItem *two = [[UIBarButtonItem alloc]initWithTitle:#"Two" style:UIBarButtonItemStylePlain target:self action:#selector(testMethod)];
UIBarButtonItem *three = [[UIBarButtonItem alloc]initWithTitle:#"Three" style:UIBarButtonItemStylePlain target:self action:#selector(testMethod)];
// create a spacer
UIBarButtonItem *space = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:self action:nil];
space.width = 30;
NSArray *buttons = #[one, space, two, space, three];
self.navigationItem.rightBarButtonItems = buttons;
}
I hate putting links as answers on SO as they can die anytime so i added relevant code taken from HERE
- (void)viewWillAppear
{
// get a view and :
[self.navigationController.navigationBar addSubView:yourView];
}

customView on left button of UINavigationBar

I'm trying to implement UINavigationBar with custom controls. So, I've added UIView on left side of UINavigationBar and trying to add controls to that UIView with following code:
UIView *view = navigationController.navigationItem.leftBarButtonItem.customView;
UIButton *button = [[UIButton alloc] initWithFrame:view.frame];
[button setTitle:#"TEST" forState:UIControlStateNormal];
[view addSubview:button];
[button sizeToFit];
[button release];
Code works, but button doesn't appear.
Any help would be appreciated.
Thank you.
UPD
OK, I gave a try to code below and made such thing:
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 40, 50)];
[button setTitle:#"XXX" forState:UIControlStateNormal];
UIBarButtonItem *customItem = [[UIBarButtonItem alloc] initWithCustomView:button];
navigationController.visibleViewController.navigationItem.leftBarButtonItem = customItem;
[customItem release];
[button release];
The "XXX" title did appear, but it looks like simple label, not button. Any ideas?
Yes, your UIButton doesn't come with any shading. What I've done is used a UISegmentedControl to get shading for free:
// Add the Menu button to the navigation bar
NSString* menuLabel = "ShadeButton";
CGSize textSize = [menuLabel sizeWithFont:[UIFont systemFontOfSize:15.0]];
UISegmentedControl* menuSegmentedButton = [[UISegmentedControl alloc]
initWithFrame:CGRectMake(0.0f, 0.0f, textSize.width, 29.0f)];
menuSegmentedButton.momentary = YES;
menuSegmentedButton.selected = NO;
menuSegmentedButton.segmentedControlStyle = UISegmentedControlStyleBar;
[menuSegmentedButton insertSegmentWithTitle:menuLabel atIndex:0
animated:NO];
[menuSegmentedButton addTarget:self action:#selector(doMenu)
forControlEvents:UIControlEventValueChanged];
UIBarButtonItem* barButton = [[UIBarButtonItem alloc]
initWithCustomView:menuSegmentedButton];
[menuSegmentedButton release];
self.navigationItem.rightBarButtonItem = barButton;
Create your UIBarButtonItem with the UISegmentedControl as shown above rather than a UIButton and you should get the effect you're after. The alternative is to do more work on the button and create a texture/custom image for it yourself.
Note quite right.
If you just want a different title:
UIBarButtonItem *customItem = [[UIBarButtonItem alloc] initWithTitle:#"TEST" style:UIBarButtonItemStylePlain target:nil action:nil];
navigationController.navigationItem.leftBarButtonItem = customItem;
[customItem release];
If you really want a custom view:
// Create Custom View called myView.
UIBarButtonItem *customItem = [[UIBarButtonItem alloc] initWithCustomView:myView];
navigationController.navigationItem.leftBarButtonItem = customItem;
[customItem release];