webentwicklung-frage-antwort-db.com.de

Negativer Abstandhalter für UIBarButtonItem in der Navigationsleiste unter iOS 11

In iOS 10 und darunter gab es eine Möglichkeit, dem Schaltflächen-Array in der Navigationsleiste einen negativen Abstandhalter hinzuzufügen:

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

Dies funktioniert unter iOS 11 nicht mehr (der Abstandhalter wird positiv statt negativ). Ich habe die Ansichtshierarchie des Balkenschaltflächenelements überprüft und es ist jetzt in _UIButtonBarStackView Eingebettet. Wie kann ich die Position der Balkenschaltfläche unter iOS 11 anpassen?

24
pckill

EDIT:

Dies funktioniert möglicherweise ab iOS 13 nicht mehr. Möglicherweise wird der Fehler angezeigt:

Clientfehler beim Versuch, die Layoutränder einer privaten Ansicht zu ändern

ALTE ANTWORT:

Ich habe in den Apple Entwicklerforen: https://forums.developer.Apple.com/thread/80075 eine etwas hackige Lösung gefunden

Es sieht so aus, als hätte das Problem damit zu tun, wie iOS 11 mit den Schaltflächen UIBarButtonItem.fixedSpace Umgeht und wie ein UINavigationBar in iOS 11 angeordnet ist. Die Navigationsleisten verwenden jetzt Autolayout und das Layout Ränder zum Anordnen der Schaltflächen. Die Lösung, die in diesem Beitrag (unten) vorgestellt wurde, bestand darin, alle Layoutränder auf einen von Ihnen gewünschten Wert zu setzen.

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
        }
    }

}

Um diese neue Navigationsleiste mit benutzerdefiniertem Schaltflächenabstand zu verwenden, müssen Sie aktualisieren, wo Sie Navigationscontroller mit dem folgenden Code erstellen:

let navController = UINavigationController(navigationBarClass: InsetButtonsNavigationBar.self, 
                                                 toolbarClass: UIToolbar.self)
navController.viewControllers = [yourRootViewController]
12
keithbhunter

Nur ein Workaround für meinen Fall, könnte es für einige Leute hilfreich sein. Das möchte ich erreichen:

enter image description here und vorher habe ich auch den negativenSpacer benutzt. Jetzt habe ich diese Lösung herausgefunden:

        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
2
Ke MA

Basierend auf der Antwort von keithbhunter habe ich eine benutzerdefinierte UINavigationBar erstellt:

NavigationBarCustomMargins.h:

#import <UIKit/UIKit.h>

@interface NavigationBarCustomMargins : UINavigationBar

@property (nonatomic) IBInspectable CGFloat leftMargin;
@property (nonatomic) IBInspectable CGFloat rightMargin;

@end

NavigationBarCustomMargins.m:

#import "NavigationBarCustomMargins.h"

#define DefaultMargin 16
#define NegativeSpacerTag 87236223

@interface NavigationBarCustomMargins ()

@property (nonatomic) BOOL leftMarginIsSet;
@property (nonatomic) BOOL rightMarginIsSet;

@end

@implementation NavigationBarCustomMargins

@synthesize leftMargin = _leftMargin;
@synthesize rightMargin = _rightMargin;

- (void)layoutSubviews {
    [super layoutSubviews];

    if (([[[UIDevice currentDevice] systemVersion] compare:@"11.0" options:NSNumericSearch] != NSOrderedAscending)) {
        BOOL isRTL = [UIApplication sharedApplication].userInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft;
        for (UIView *view in self.subviews) {
            view.layoutMargins = UIEdgeInsetsMake(0, isRTL ? self.rightMargin : self.leftMargin, 0, isRTL ? self.leftMargin : self.rightMargin);
        }
    } else {
        //left
        NSMutableArray *leftItems = [self.topItem.leftBarButtonItems mutableCopy];
        if (((UIBarButtonItem *)leftItems.firstObject).tag != NegativeSpacerTag) {

            UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
            negativeSpacer.tag = NegativeSpacerTag;
            negativeSpacer.width = self.leftMargin - DefaultMargin;
            [leftItems insertObject:negativeSpacer atIndex:0];

            [self.topItem setLeftBarButtonItems:[leftItems copy] animated:NO];
        }

        //right
        NSMutableArray *rightItems = [self.topItem.rightBarButtonItems mutableCopy];
        if (((UIBarButtonItem *)rightItems.firstObject).tag != NegativeSpacerTag) {

            UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
            negativeSpacer.tag = NegativeSpacerTag;
            negativeSpacer.width = self.rightMargin - DefaultMargin;
            [rightItems insertObject:negativeSpacer atIndex:0];
            [self.topItem setRightBarButtonItems:[rightItems copy] animated:NO];
        }
    }
}

- (CGFloat)leftMargin {
    if (_leftMarginIsSet) {
        return _leftMargin;
    }
    return DefaultMargin;
}

- (CGFloat)rightMargin {
    if (_rightMarginIsSet) {
        return _rightMargin;
    }
    return DefaultMargin;
}

- (void)setLeftMargin:(CGFloat)leftMargin {
    _leftMargin = leftMargin;
    _leftMarginIsSet = YES;
}

- (void)setRightMargin:(CGFloat)rightMargin {
    _rightMargin = rightMargin;
    _rightMarginIsSet = YES;
}

@end

Danach habe ich im Interface Builder die benutzerdefinierte Klasse für meinen UINavigationController festgelegt und nur die erforderlichen Ränder festgelegt: Screenshot 1

Funktioniert gut. Unterstützt RTL und iOS vor 11: Screenshot 2

1