iOS 11 - UIBarButtonItem horizontal position

There used to be a way, on iOS 10 and below, to shift/position custom-view-UIBarButtonItems set on the left/rightBarButtonItems closer to the screen edges using a negative spacer outlined here:


This trick no longer works on iOS 11 with the new auto layout support in the navigation bar. Is there another means of shifting the left/right buttons closer to the screen edge?

if (self.position == BarButtonViewPositionLeft){

[view.superview addConstraint:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeLeading /

applied = YES;

}

->>

if (self.position == BarButtonViewPositionLeft){

for(NSLayoutConstraint *ctr in view.constraints) {

if(ctr.firstAttribute == NSLayoutAttributeLeading || ctr.secondAttribute == NSLayoutAttributeLeading) {

ctr.constant = 8.f;

}

}

applied = YES;

}

It seems this is the only way, I guess navigationBar layout uses its own margins , so ignore the constraints set out of its own class.


- (void)layoutSubviews {
    [super layoutSubviews];
   
    if (@available(iOS 11, *)) {
        self.layoutMargins = UIEdgeInsetsZero;
       
        for (UIView *subview in self.subviews) {
            if ([NSStringFromClass([subview class]) containsString:@"ContentView"]) {
                UIEdgeInsets oEdges = subview.layoutMargins;
                subview.layoutMargins = UIEdgeInsetsMake(0, 0, 0, oEdges.right);
            }
        }
    }
}

Thanks, wang_stg.

Your solution worked for me.


Here is swift version of the code: (SnapKit is used for defining constraints)


import UIKit


enum BarButtonPosition {

case left

case right

}

public class BarButton: UIButton {

var position: BarButtonPosition! = .left

private var applied: Bool = false


override public func layoutSubviews() {

super.layoutSubviews()

let os_version = OperatingSystemVersion(majorVersion: 11, minorVersion: 0, patchVersion: 0)

if applied || !ProcessInfo.processInfo.isOperatingSystemAtLeast(os_version) {

return

}

var view: UIView! = self

while (!view.isKind(of: UINavigationBar.self) && view.superview != nil) {

if let stackView = view.superview {

if (stackView.isKind(of: UIStackView.self) && stackView.superview != nil) {

if self.position == .left {

stackView.snp.makeConstraints({ (make) in

make.leading.equalToSuperview().offset(8)

})

applied = true

} else if self.position == .right {

stackView.snp.makeConstraints({ (make) in

make.trailing.equalToSuperview().offset(-8)

})

applied = true

}

break

}

view = stackView

}

}

}

}

iOS 11 - UIBarButtonItem horizontal position
 
 
Q