33

I have created a navigation bar with left bar button item added from storyboard, titleView and three right bar button items from code.

Here is the code:

override func viewDidLoad() {
    super.viewDidLoad()

    var screenWidth = UIScreen.mainScreen().bounds.width
    // custom title view
    var navBarWidth: CGFloat = self.navigationController!.navigationBar.frame.size.width
    let customTitleView = UIView(frame: CGRectMake(0, 0, navBarWidth, 44))
    titleLabel = UILabel(frame: CGRectMake(20, 0, navBarWidth, 40))
    titleLabel.text = conversationName
    if let titleFont = UIFont(name: "Roboto-Regular", size: 20) {
        titleLabel.font = titleFont
    }
    titleLabel.textColor = UIColor.whiteColor()

    customTitleView.addSubview(titleLabel)
    self.navigationItem.titleView = customTitleView

    // right bar buttons
    var searchImage = UIImage(named: "search")!
    var clipImage = UIImage(named: "clip")!
    var pencilImage = UIImage(named: "pencil")!

    var searchBtn = UIBarButtonItem(image: searchImage, style: UIBarButtonItemStyle.Plain, target: self, action: Selector("searchBtnPressed"))
    searchBtn.tintColor = UIColor.whiteColor()
    var clipBtn = UIBarButtonItem(image: clipImage, style: UIBarButtonItemStyle.Plain, target: self, action: Selector("clipBtnPressed"))
    clipBtn.tintColor = UIColor.whiteColor()
    var pencilBtn = UIBarButtonItem(image: pencilImage, style: UIBarButtonItemStyle.Plain, target: self, action: Selector("pencilBtnPressed"))
    pencilBtn.tintColor = UIColor.whiteColor()

    self.navigationItem.setRightBarButtonItems([pencilBtn, clipBtn, searchBtn], animated: false)
}

My problem is that I want to change the spacing between right buttons but I don't know how.

I've tried to add a fixedButton between them but it just increased the existing space.

Can some one help me? Thanks.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
mkz
  • 2,302
  • 2
  • 30
  • 43

9 Answers9

76

I solved my problem in this way:

var searchImage = UIImage(named: "search-selected")!
var clipImage = UIImage(named: "clip")!
var pencilImage = UIImage(named: "pencil")!

let searchBtn: UIButton = UIButton.buttonWithType(UIButtonType.Custom) as! UIButton
searchBtn.setImage(searchImage, forState: UIControlState.Normal)
searchBtn.addTarget(self, action: "searchBtnPressed", forControlEvents: UIControlEvents.TouchUpInside)
searchBtn.frame = CGRectMake(0, 0, 30, 30)
let searchBarBtn = UIBarButtonItem(customView: searchBtn)

let clipBtn: UIButton = UIButton.buttonWithType(UIButtonType.Custom) as! UIButton
clipBtn.setImage(clipImage, forState: UIControlState.Normal)
clipBtn.addTarget(self, action: "clipBtnPressed", forControlEvents: UIControlEvents.TouchUpInside)
clipBtn.frame = CGRectMake(0, 0, 30, 30)
let clipBarBtn = UIBarButtonItem(customView: clipBtn)

let pencilBtn: UIButton = UIButton.buttonWithType(UIButtonType.Custom) as! UIButton
pencilBtn.setImage(pencilImage, forState: UIControlState.Normal)
pencilBtn.addTarget(self, action: "pencilBtnPressed", forControlEvents: UIControlEvents.TouchUpInside)
pencilBtn.frame = CGRectMake(0, 0, 30, 30)
let pencilBarBtn = UIBarButtonItem(customView: pencilBtn)

self.navigationItem.setRightBarButtonItems([pencilBarBtn, clipBarBtn, searchBarBtn], animated: false)

Now it looks good,

Difference between before and after

Update for Swift 4.1

let testButton : UIButton = UIButton.init(type: .custom)
testButton.setImage(editImage, for: .normal)
testButton.addTarget(self, action: #selector(didTapCameraButton), for: .touchUpInside)
testButton.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
let addButton = UIBarButtonItem(customView: testButton)
TheTiger
  • 13,264
  • 3
  • 57
  • 82
mkz
  • 2,302
  • 2
  • 30
  • 43
  • You could well use a function instead of repeating all that code. But, well thanks it worked! – LaloLoop Feb 24 '17 at 04:08
  • a perfect answer I love this. so below i going to give the answer in objective c – Anup Gupta Dec 22 '17 at 12:50
  • Exactly what I was looking for, however setting the frame was not neccessary for me, so I left that line. – balazs630 Mar 06 '19 at 13:24
  • But what if those bar buttons are not custom bar buttons, but provided by system like "Done", "Camera" or "Edit". – Ashutosh Shukla Jun 07 '19 at 07:19
  • Just using the `customView` initializer instead of the one with `image` gave me the correct result, since the image had not insets as it seems. – Skoua Jun 13 '20 at 09:06
  • @mkz tintColor was not able to set with this approach any thoughts on applying tintColor? – iOSDude Sep 29 '21 at 19:43
7

Set testButton.frame doesn't help.

This solution is correct for me!

rightButton.imageEdgeInsets = UIEdgeInsets(top: 3, left: 10, bottom: 7, right: 0)
Praveenkumar
  • 24,084
  • 23
  • 95
  • 173
IvanPavliuk
  • 1,460
  • 1
  • 21
  • 16
5

For Swift 3:

let searchBtn: UIButton = UIButton(type: UIButtonType.custom)
searchBtn.setImage(UIImage(named: "search"), for: [])
searchBtn.addTarget(self, action: #selector(ViewController.searchBtnPressed(_:)), for: UIControlEvents.touchUpInside)
searchBtn.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
let searchButton = UIBarButtonItem(customView: searchBtn)

let clipBtn: UIButton = UIButton(type: UIButtonType.custom)
clipBtn.setImage(UIImage(named: "clip"), for: [])
clipBtn.addTarget(self, action: #selector(ViewController.clipBtnPressed(_:)), for: UIControlEvents.touchUpInside)
clipBtn.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
let clipButton = UIBarButtonItem(customView: clipBtn)

let pencilBtn: UIButton = UIButton(type: UIButtonType.custom)
pencilBtn.setImage(UIImage(named: "pencil"), for: [])
pencilBtn.addTarget(self, action: #selector(ViewController.pencilBtnPressed(_:)), for: UIControlEvents.touchUpInside)
pencilBtn.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
let pencilButton = UIBarButtonItem(customView: pencilBtn)

self.navigationItem.rightBarButtonItems = [pencilButton, clipButton, searchButton]

Replace ViewController with your view controller

Jeremy Bader
  • 382
  • 1
  • 6
  • 14
3
// create three nav bar buttons
    var searchBtn = UIBarButtonItem(image: searchImage, style: UIBarButtonItemStyle.Plain, target: self, action: Selector("searchBtnPressed"))
    searchBtn.tintColor = UIColor.whiteColor()
    var clipBtn = UIBarButtonItem(image: clipImage, style: UIBarButtonItemStyle.Plain, target: self, action: Selector("clipBtnPressed"))
    clipBtn.tintColor = UIColor.whiteColor()
    var pencilBtn = UIBarButtonItem(image: pencilImage, style: UIBarButtonItemStyle.Plain, target: self, action: Selector("pencilBtnPressed"))
    pencilBtn.tintColor = UIColor.whiteColor()

// create a spacer
  var space = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: self, action: nil)
  space.width = 10

  var buttons = [pencilBtn, space, clipBtn, space, searchBtn]
  navigationItem?.rightBarButtonItems = buttons
Sourabh Kumbhar
  • 1,034
  • 14
  • 12
2

This solution is in Objective C

UIImage *settingImageName = [UIImage imageNamed:@"Menu_Burger_Icon"];
UIButton * settingButton = [UIButton buttonWithType:UIButtonTypeCustom];
[settingButton setImage:settingImageName forState:UIControlStateNormal];
[settingButton addTarget:self action:@selector(settingsBtnClicked) forControlEvents:UIControlEventTouchUpInside];
settingButton.frame = CGRectMake(0, 0, 30, 30);

UIBarButtonItem *settingBarButton = [[UIBarButtonItem alloc] initWithCustomView:settingButton];

UIImage *notificationImageName = [UIImage imageNamed:@"NotificationON"];
UIButton * notificationButton = [UIButton buttonWithType:UIButtonTypeCustom];
[notificationButton setImage:notificationImageName forState:UIControlStateNormal];
[notificationButton addTarget:self action:@selector(notificationButtonClicked) forControlEvents:UIControlEventTouchUpInside];
notificationButton.frame = CGRectMake(0, 0, 30, 30);
UIBarButtonItem *notificationBarButton = [[UIBarButtonItem alloc] initWithCustomView:notificationButton];

self.navigationItem.rightBarButtonItems  = @[settingBarButton,notificationBarButton];

Solution reference by @mikle94. His answer is in Swift.

Praveenkumar
  • 24,084
  • 23
  • 95
  • 173
Anup Gupta
  • 1,993
  • 2
  • 25
  • 40
  • this works as expected for me but the problem is I want to apply tint color to the button I tried as below but it was not working can you check once. **settingButton.tintColor = [UIColor blackColor]; settingBarButton.tintColor = [UIColor blackColor];** – iOSDude Sep 29 '21 at 19:19
  • Unable to set tintColor with this approach any thoughts on applying tintColor? – iOSDude Sep 29 '21 at 19:45
1
let rightActionButton:UIButton = UIButton()

if #available(iOS 11.0, *) {

    let widthConstraint = rightActionButton.widthAnchor.constraint(equalToConstant: 30)
    let heightConstraint = rightActionButton.heightAnchor.constraint(equalToConstant: 30)
    heightConstraint.isActive = true
    widthConstraint.isActive = true
}
else {
    rightActionButton.frame = CGRect.init(x: 0, y: 0, width: 30, height: 30)
}

rightActionButton.setImage(UIImage.init(named: "3-dots-right-button"), for: .normal)
rightActionButton.addTarget(self, action: #selector(handleRightMenu), for: UIControlEvents.touchUpInside)
rightActionButton.setTitle("", for: .normal)
rightActionButton.tintColor = UIColor(hex:K.NODD_GREEN_HEX)


let rightActionBarButton:UIBarButtonItem = UIBarButtonItem(customView: rightActionButton)

let rightBarButtonItem1 = rightActionBarButton
let rightBarButtonItem2 = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(handleRight2Menu))

self.navigationItem.rightBarButtonItems = [rightBarButtonItem1,rightBarButtonItem2]
Community
  • 1
  • 1
Urvish Modi
  • 1,118
  • 10
  • 11
0

Try to change the constraintEqualToConstant

[myUIButton.widthAnchor constraintEqualToConstant:24].active = YES;
[myUIButton.heightAnchor constraintEqualToConstant:24].active = YES;
Mutawe
  • 6,464
  • 3
  • 47
  • 90
0

You can also wire things up first in Storyboard.
I have two right bar button items.

(This is objective-c code, which you can modify for swift.)

First create references to them in view controller.

@interface MyViewController ()
    @property (weak, nonatomic) IBOutlet UIButton *smsButton;
    @property (weak, nonatomic) IBOutlet UIButton *checkoutButton;
@end

Then, in viewDidLoad, adjust their widths and heights.

// Adjust right bar button item spacing.
self.smsButton.frame = CGRectMake(0, 0, 30, 30);
self.lockButton.frame = CGRectMake(0, 0, 30, 30);
Praveenkumar
  • 24,084
  • 23
  • 95
  • 173
lazarus
  • 21
  • 1
0

Supporting solution by @mkz, by using function to reduce the code (Swift 4.2.1)

Added most important parameters to the function (note how to pass selector to a function), you may want to add more as per your need.

func makeCustomNavigationButton(imageName: String, action: Selector) -> UIBarButtonItem{

    let image = UIImage(named: imageName)!
    let btn: UIButton = UIButton(type: UIButton.ButtonType.custom)
    btn.setImage(image, for: .normal)
    btn.addTarget(self, action: action, for: .touchUpInside)
    btn.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
    let barBtn = UIBarButtonItem(customView: btn)

    return barBtn
}

How to call:

let search = self.makeCustomNavigationButton(imageName: "search", action: #selector(searchBtnPressed(_:)))
let clip = self.makeCustomNavigationButton(imageName: "clip", action: #selector(clipBtnPressed(_:)))
let pencil = self.makeCustomNavigationButton(imageName: "pencil", action: #selector(pencilBtnPressed(_:)))
self.navigationItem.rightBarButtonItems = [search, clip, pencil]
Farhan Arshad
  • 375
  • 3
  • 9