How to adjust space between two UIBarButtonItem in rightBarButtonItems
Solution 1
Updated at Jul 2015
A better way to do this is to use storyboard (tested in Xcode 6.4). First, add a UINavigationItem; secondly, add a Bar Button Item; thirdly, add a view to the Bar Button Item you just created in step 2; fourthly, add as many buttons as you wish into that view you just dragged in; lastly, adjust the space with your mouse and constraints.
Related Questions
Can't assign multiple Buttons to UINavigationItem when using Storyboard with iOS 5
How to add buttons to navigation controller visible after segueing?
Old Answer (Only acceptable for small insets)
Use imageInsets property:
leftButton.imageInsets = UIEdgeInsetsMake(0.0, 0.0, 0, -15);
rightButton.imageInsets = UIEdgeInsetsMake(0.0, -15, 0, 0);
for three or more buttons, the middle one(s) get both insets:
leftButton.imageInsets = UIEdgeInsetsMake(0.0, 0.0, 0, -15);
middleButton.imageInsets = UIEdgeInsetsMake(0.0, -15, 0, -15);
rightButton.imageInsets = UIEdgeInsetsMake(0.0, -15, 0, 0);
For the right side buttons, be careful: the FIRST button in the item array is the RIGHT one:
rightButton.imageInsets = UIEdgeInsetsMake(0.0, -15, 0, 0);
middleButton.imageInsets = UIEdgeInsetsMake(0.0, -15, 0, -15);
leftButton.imageInsets = UIEdgeInsetsMake(0.0, 0.0, 0, -15);
IMPORTANT: Split the inset between the two neighbors; if apply the entire inset to one edge, it will become obvious that the buttons are overlapping in the "blank" space - one button gets all of the "gap" touches. Even when "split" the adjustment like this, at -40 on both edges, the tap will definitely go to wrong button sometimes. -15 or -20 is the most to consider using with this technique.
By applying this method, the button could even be moved around in four directions.
Solution 2
My solution is using a custom view for right bar buttons. Create a horizontal stackview with equal spacing and add any number of buttons as subview.
Sample code:
func addRightBarButtonItems()
{
let btnSearch = UIButton.init(type: .custom)
btnSearch.setImage(UIImage(systemName: "magnifyingglass"), for: .normal)
btnSearch.addTarget(self, action: #selector(MyPageContainerViewController.searchButtonPressed), for: .touchUpInside)
let btnEdit = UIButton.init(type: .custom)
btnEdit.setImage(UIImage(systemName: "pencil"), for: .normal)
btnEdit.addTarget(self, action: #selector(MyPageContainerViewController.editButtonPressed), for: .touchUpInside)
let stackview = UIStackView.init(arrangedSubviews: [btnEdit, btnSearch])
stackview.distribution = .equalSpacing
stackview.axis = .horizontal
stackview.alignment = .center
stackview.spacing = 8
let rightBarButton = UIBarButtonItem(customView: stackview)
self.navigationItem.rightBarButtonItem = rightBarButton
}
Solution 3
Swift 5
In your AppDelegate add this code:
let stackViewAppearance = UIStackView.appearance(whenContainedInInstancesOf: [UINavigationBar.self])
stackViewAppearance.spacing = -10
This will work with no additional code in more recent SDK versions as UIBarButtonItems
are already contained in a horizontal UIStackView
Solution 4
First:
For UIBarButtonItem
you must use constructor init(customView: UIView)
Second:
Use fixedSpace
for set space between buttons
example:
let firstButton = UIButton()
let firstButtonItem = UIBarButtonItem(customView: firstButton)
let secondButton = UIButton()
let secondButtonItem = UIBarButtonItem(customView: secondButton)
let space = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
space.width = WIDTH
self.navigationItem.rightBarButtonItems = [firstButtonItem, space, secondButtonItem]
Solution 5
One line of code is all you need to decrease the space between buttons in the navigation bar:
UIStackView.appearance(whenContainedInInstancesOf: [UINavigationBar.self]).spacing = -10
You must place this line in your code before you add the buttons to the navigation bar.
Related videos on Youtube
Comments
-
Bob almost 2 years
I am using the following codes to add two button to self.navigationItem.rightBarButtonItems, and I think in iOS7, the space between two buttons are too wide, is there a way to decrease the space between these two buttons?
UIBarButtonItem *saveStyleButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"save.png"] style:UIBarButtonItemStyleBordered target:self action:@selector(saveStyle)]; UIBarButtonItem *shareStyleButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(shareStyle)]; NSArray *arr= [[NSArray alloc] initWithObjects:shareStyleButton,saveStyleButton,nil]; self.navigationItem.rightBarButtonItems=arr;
Appreciate any hint or idea.
-
Bob over 10 yearsTried both, but neither works. It seems that there is a minimal value which couldn't be overwritten.
-
Joride over 10 yearsMaybe try wit custom view see how small you can make that custom view to find out if there is a lower limit. I guess that the system ones are just as they are and pretty much immutable (unless you hack something maybe).
-
Bob over 10 yearsholy crap, i solve it myself with just one more line of code!
-
Bob over 10 yearsThe code is saveStyleButton.imageInsets = UIEdgeInsetsMake(0.0, 0.0, 0, -50);
-
Bob over 10 yearsAnd I think by applying this method the button could be even be moved around in four directions! what a bonus point!
-
tybro0103 about 10 yearsWhile this will move the image, it does not move the tap-able area.
-
Aron Lindberg over 9 yearsTo preserve the tap-able area you want to edit the imageInsets on both the left and right UIBarButtonItem like this:
firstButton.imageInsets = UIEdgeInsetsMake(0, 0, 0, -25); secondButton.imageInsets = UIEdgeInsetsMake(0, -25, 0, 0);
-
Ramesh about 9 yearsTried negative insets, visuals are properly adjusted; but, tap is not accurate. E.g. If you have 3 button and used the imageInsets to make the spacing tighter, the tap on button is not mapped to the actual button.
-
Alphonse R. Dsouza over 8 yearsIt worked perfectly with Storyboard and UIBarbuttonItem with customView
-
ToolmakerSteve over 7 yearsHow can you add some space between these buttons?
-
ToolmakerSteve over 7 yearsTrying on iOS 10.2: positive values of width work, the neighboring buttons are farther apart, but negative value has same result as zero value: the neighboring buttons are at the same locations as if the FixedSpace spacer was not there. I suspect they have nullified this ability to overlap items.
-
ToolmakerSteve over 7 yearsFWIW: the old approach, negativeInsets, are a tolerable hack for small value such as -10, but for larger values you soon discover that the buttons are actually overlapping: one of the buttons is "in front", and gets the tap anywhere in the overlapping area. I mention this because if one only needs a small tweak, setting negativeInset is easy to do in code, so is tempting - just don't adjust too far.
-
ToolmakerSteve over 7 years@AronLindberg - "splitting" the image-insets between the buttons does help, but be aware that the buttons do still end up with some overlap. This can be seen with a large offset, especially in emulator, where can use a mouse to see exactly where the touch is. The technique seems fine for -10 from each side, but is borderline at -25. At -40, its a definite fail in my tests; with three buttons, the middle one is receiving tap over the entire (small) visual gap - even slightly into the edge of neighbor button's icon. emulator, iOS 10.2, iPhone SE, 44 pixel icons (22@x2).
-
Slobodan Antonijević about 7 yearsThe updated part here worked perfectly for me, as I only needed the logo image to display on the right, and not in center as title. And simply disabling the button did the trick. thumbs up @Bob
-
Glenn Posadas over 5 yearsThis is so perfect! Thank you for this. Such a shame that an experienced iOS engr like me struggles with handling back buttons in iOS whenever the project has so multiple custom nav bar designs! Although I had to adjust and test lots of times my implementation using this code for different iOS versions. Thanks again.
-
Rishab over 5 yearsThis is a good solution. However, if the
title
of view controller is too big this spacing is neglected. -
Micah Montoya about 5 yearsThis works for swift 4 if the numbers are positive.
-
Lance Samaria over 4 yearsThis worked for me but to bring them really close to each other I set: stackview.spacing = 0
-
Muhammad Danish Qureshi almost 3 yearsVery Good solution...! Thanks...!
-
iOSDude over 2 years@AronLindberg reduce space between 3 buttons. I've 3 right bar buttons I want reduce the default space between them, all 3 created programmatically in Objective C. When I add this values it increases the space between buttons and if i make -15 to -5 it was space as like default space is there any way to reduce space between 3 buttons????. **firstButton.imageInsets = UIEdgeInsetsMake(0.0, -15, 0, 0); secondButton.imageInsets = UIEdgeInsetsMake(0.0, -15, 0, -15); thirdButton.imageInsets = UIEdgeInsetsMake(0.0, 0.0, 0, -15); **
-
Binaya Thapa Magar over 2 yearsHi a newbie here, how do you set the height and width of buttons then?
-
Natalia Terlecka about 2 yearsPerfect, worked for me