0

In my app, I have a navigation bar where I'm using three buttons on the right side. I create it like this:

let button1 = UIBarButtonItem(image: UIImage(named: "button1"),
                              style: .plain,
                              target: self,
                              action: #selector(self.button1Tapped))

// Repeat for button2 and button3

navigationItem.rightBarButtonItems = [button1, button2, button3]

This works as expected, except on iPhone SE. It seems like there is some sort of fixed limit on what percentage of the navigation bar width the right bar buttons can take up, and this limit is exceeded on the small screen of the iPhone SE. So, the rightmost button gets shrunk down to about half the size of the other buttons.

I'm not setting a title, so there's more than enough space for all 3 buttons to be full size - even on iPhone SE. However, I'm not sure how to specify that in code; is there some way to increase this limit (or whatever feature causes the button to shrink) to ensure that all of the BarButtonItems appear full size on iPhone SE?

kmell96
  • 1,365
  • 1
  • 15
  • 39

2 Answers2

1

This isn't the most eloquent way of doing things but it should work.

The iPhone SE screen's dimensions are w:320 x h:568 Apple Screen Display Sizes

You could possibly resize the images for the iPhone SE and do something like this:

var button1: UIBarButtonItem!
var button2: UIBarButtonItem!
var button2: UIBarButtonItem!

// check the screen's dimensions
if UIScreen.main.bounds.width == 320 && UIScreen.main.bounds.height == 568{

    // you may have to play around with it but resize the UIImage(named: "button1") to fit the iPhone SE
    button1 = UIBarButtonItem(image: UIImage(named: "button1_Resized"),
                              style: .plain,
                              target: self,
                              action: #selector(self.button1Tapped))

    // Repeat for button2 and button3
    // resize the UIImage(named: "button2_Resized") and UIImage(named: "button3_Resized") to fit the iPhone SE

} else{

    // anything other then the iPhone SE will get the regular sized images
    button1 = UIBarButtonItem(image: UIImage(named: "button1"),
                              style: .plain,
                              target: self,
                              action: #selector(self.button1Tapped))

    // Repeat for button2 and button3
}

navigationItem.rightBarButtonItems = [button1, button2, button3]
Lance Samaria
  • 17,576
  • 18
  • 108
  • 256
  • That doesn't really help with my problem because the navigation bar is the same height on the iPhone SE as on any other device, so I want the buttons to be the same height (and same width to keep the aspect ratio) on all devices as well. It looks like your solution would cause all 3 images to shrink, not to mention that I'd have to have twice as many image assets. – kmell96 Apr 26 '18 at 04:55
  • 1
    Your right once you resize the images they would be smaller on the SE. That's why I asked you under the question were the images all the same sizes and in my answer I said "This isn't the most eloquent way of doing things but it should work". You do have to do the extra work of playing around with the images and resize them for the SE :( I was in the same situation as you and this is what I used to work around the iPhone SE's navBar. Just another option. Hope you find an answer! Good luck coding :) – Lance Samaria Apr 26 '18 at 04:59
  • I actually ended up using this solution anyway. It's easier than trying to figure out an elegant fix that actually does what I want, and it doesn't look that bad. Thanks! – kmell96 Apr 26 '18 at 05:28
  • Np, glad I can help. – Lance Samaria Apr 26 '18 at 05:29
0

You can declare these properties

let contentView = UIView()
let buttonOneImageView = UIImageView()
let buttonTwoImageView = UIImageView()
let buttonThreeImageView = UIImageView()

assign a UIView to titleView property of navigationItem of ViewController as a workaround

fileprivate func buttonOneImageViewConstraints() {
    buttonOneImageView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
    buttonOneImageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
    buttonOneImageView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -8).isActive = true
    buttonOneImageView.widthAnchor.constraint(equalTo: buttonOneImageView.heightAnchor).isActive = true
}

fileprivate func buttonOneConstraints(_ button1: UIButton) {
    //button1 constraints
    button1.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
    button1.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
    button1.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -8).isActive = true
    button1.widthAnchor.constraint(equalTo: button1.heightAnchor).isActive = true
}

fileprivate func buttonTwoImageViewConstraints() {
    buttonTwoImageView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
    buttonTwoImageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
    buttonTwoImageView.rightAnchor.constraint(equalTo: buttonOneImageView.leftAnchor, constant: -8).isActive = true
    buttonTwoImageView.widthAnchor.constraint(equalTo: buttonTwoImageView.heightAnchor).isActive = true
}

fileprivate func buttonTwoConstraints(_ button1: UIButton,_ button2: UIButton) {
    //button2 constraints
    button2.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
    button2.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
    button2.rightAnchor.constraint(equalTo: button1.leftAnchor, constant: -8).isActive = true
    button2.widthAnchor.constraint(equalTo: button2.heightAnchor).isActive = true
}

fileprivate func buttonThreeImageViewConstraints() {
    buttonThreeImageView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
    buttonThreeImageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
    buttonThreeImageView.rightAnchor.constraint(equalTo: buttonTwoImageView.leftAnchor, constant: -8).isActive = true
    buttonThreeImageView.widthAnchor.constraint(equalTo: buttonThreeImageView.heightAnchor).isActive = true
}

fileprivate func buttonThreeConstraints(_ button2: UIButton,_ button3: UIButton) {
    //button3 constraints
    button3.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
    button3.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
    button3.rightAnchor.constraint(equalTo: button2.leftAnchor, constant: -8).isActive = true
    button3.widthAnchor.constraint(equalTo: button3.heightAnchor).isActive = true
}

fileprivate func contentViewConstraints(_ titleView: UIView) {
    //setting constraints for contentView
    contentView.rightAnchor.constraint(equalTo: titleView.rightAnchor).isActive = true
    contentView.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width).isActive = true
    contentView.centerXAnchor.constraint(equalTo: titleView.centerXAnchor).isActive = true
    contentView.centerYAnchor.constraint(equalTo: titleView.centerYAnchor).isActive = true
    self.navigationItem.titleView = titleView
}

func setupNavBar() {

    contentView.backgroundColor = .black
    contentView.translatesAutoresizingMaskIntoConstraints = false

    let titleView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 40))
    titleView.addSubview(contentView)


    buttonOneImageView.translatesAutoresizingMaskIntoConstraints = false
    buttonOneImageView.contentMode = .scaleAspectFit
    buttonOneImageView.image = #imageLiteral(resourceName: "contacts-settings")
    contentView.addSubview(buttonOneImageView)

    //add button1
    let button1 = UIButton(type: .roundedRect)
    button1.translatesAutoresizingMaskIntoConstraints = false
    button1.addTarget(self, action: #selector(buttonOneFunction), for: .touchUpInside)
    contentView.addSubview(button1)

    buttonTwoImageView.translatesAutoresizingMaskIntoConstraints = false
    buttonTwoImageView.contentMode = .scaleAspectFit
    buttonTwoImageView.image = #imageLiteral(resourceName: "contacts-history")
    contentView.addSubview(buttonTwoImageView)

    //add button2
    let button2 = UIButton(type: .roundedRect)
    button2.translatesAutoresizingMaskIntoConstraints = false
    button2.addTarget(self, action: #selector(buttonTwoFunction), for: .touchUpInside)
    contentView.addSubview(button2)

    buttonThreeImageView.translatesAutoresizingMaskIntoConstraints = false
    buttonThreeImageView.contentMode = .scaleAspectFit
    buttonThreeImageView.image = #imageLiteral(resourceName: "contacts-person")
    contentView.addSubview(buttonThreeImageView)

    //add button3
    let button3 = UIButton(type: .roundedRect)
    button3.translatesAutoresizingMaskIntoConstraints = false
    button3.addTarget(self, action: #selector(buttonThreeFunction), for: .touchUpInside)
    contentView.addSubview(button3)


    DispatchQueue.main.asyncAfter(deadline: .now()) {
        self.buttonOneImageViewConstraints()
        self.buttonOneConstraints(button1)
        self.buttonTwoImageViewConstraints()
        self.buttonTwoConstraints(button1, button2)
        self.buttonThreeImageViewConstraints()
        self.buttonThreeConstraints(button2, button3)
        self.contentViewConstraints(titleView)
    }

}

Similarly,

@objc func buttonTwoFunction() {
    print("button 2 tapped")
}

@objc func buttonThreeFunction() {
    print("button 3 tapped")
}
N4SK
  • 700
  • 8
  • 25
  • I like this approach; I tried your code and all three items are now the correct size. But, there were two issues: all three items now appear in the center of the screen instead of on the right, and the items are overlapping. – kmell96 Apr 26 '18 at 05:04
  • One issue with this approach is that bar buttons behave differently than UIButtons when displaying popover views on iPad (which I use these buttons to display). If possible, I'd like to keep using bar buttons to keep the popover behavior. – kmell96 Apr 26 '18 at 05:05
  • I update the code for making the buttons appear on right side... check if that works... of course these are UIButton so they won't work similar to UIBarButton... You may have to add those functionality manually – N4SK Apr 26 '18 at 05:09
  • Thanks, that looks better. But, I can't click on any of the buttons. It seems like title views might not allow user interaction. – kmell96 Apr 26 '18 at 05:18