Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Negative spacer for UIBarButtonItem in navigation bar on iOS 11

Tags:

In iOS 10 and below, there was a way to add a negative spacer to the buttons array in the navigation bar, like so:

UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; negativeSpacer.width = -8; self.navigationItem.leftBarButtonItems = @[negativeSpacer, [self backButtonItem]]; 

This no longer works on iOS 11 (the spacer becomes positive, instead of negative). I have inspected the view hierarchy of the bar button item, and it is now embedded into _UIButtonBarStackView. How to adjust the position of the bar button on iOS 11?

like image 755
pckill Avatar asked Aug 07 '17 10:08

pckill


People also ask

How do I change my Apple navigation bar?

On your Mac, use Dock & Menu Bar System Preferences to change the appearance of the Dock, and to select items to show in the menu bar and in Control Center. To change these preferences, choose Apple menu > System Preferences, then click Dock & Menu Bar .

How do I customize the navigation bar in Swift?

Go to the ViewController. swift file and add the ViewDidAppear method. a nav helper variable which saves typing. the Navigation Bar Style is set to black and the tint color is set to yellow, this will change the bar button items to yellow.

How do I use the navigation bar in Xcode?

Start with Navigation ControllerCreate a single view application in Xcode. Add two view controller into your storyboard. Create two different swift files for those view controllers and set identifiers for them. Take a button in each view controller, set constrain for them and customize as you want.


2 Answers

EDIT:

This may no longer work as of iOS 13. You may get the error:

Client error attempting to change layout margins of a private view

OLD ANSWER:

I found a somewhat hacky solution on the Apple developer forums: https://forums.developer.apple.com/thread/80075

It looks like the problem comes from how iOS 11 handles the UIBarButtonItem .fixedSpace buttons and how a UINavigationBar is laid out in iOS 11. The navigation bars now use autolayout and the layout margins to layout the buttons. The solution presented in that post (at the bottom) was to set all the layout margins to some value you want.

class InsetButtonsNavigationBar: UINavigationBar {      override func layoutSubviews() {         super.layoutSubviews()          for view in subviews {             // Setting the layout margins to 0 lines the bar buttons items up at             // the edges of the screen. You can set this to any number to change             // the spacing.             view.layoutMargins = .zero         }     }  } 

To use this new nav bar with custom button spacing, you will need to update where you create any navigation controllers with the following code:

let navController = UINavigationController(navigationBarClass: InsetButtonsNavigationBar.self,                                                   toolbarClass: UIToolbar.self) navController.viewControllers = [yourRootViewController] 
like image 90
keithbhunter Avatar answered Nov 03 '22 00:11

keithbhunter


Just a workaround for my case, it might be helpful to some people. I would like to achieve this:

enter image description here and previously I was using the negativeSpacer as well. Now I figured out this solution:

        let logoImage = UIImage(named: "your_image")         let logoImageView = UIImageView(image: logoImage)         logoImageView.frame = CGRect(x: -16, y: 0, width: 150, height: 44)         logoImageView.contentMode = .scaleAspectFit         let logoView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 44))         **logoView.clipsToBounds = false**         logoView.addSubview(logoImageView)         let logoItem = UIBarButtonItem(customView: logoView)         navigationItem.leftBarButtonItem = logoItem 
like image 39
Ke MA Avatar answered Nov 03 '22 01:11

Ke MA