So bearbeiten Sie leere Bereiche des linken, rechten UIBarButtonItem in der UINavigationBar [iOS 7]

83

Ich habe früher iOS 6.1 verwendet, bin jetzt aber zu iOS 7 übergegangen. Zusammen mit anderen Problemen habe ich festgestellt, dass in meiner Navigationsleiste der linke Bereich des linken Balkenschaltflächenelements und der rechte leere Bereich des rechten Schaltflächenleistenelements recht groß sind mehr in IOS 7 als in iOS 6.

Ich muss wissen, ob es eine Möglichkeit gibt, Leerzeichen von Schaltflächenelementen in der linken und rechten Leiste in der Navigationsleiste zu reduzieren.

Danke im Voraus.

Salman Zaidi
quelle
2
Versuchen Sie dies: github.com/devxoul/UINavigationItem-Margin
devxoul

Antworten:

220

Ich war auch mit diesem Problem konfrontiert. Ich habe auch das Gefühl, dass in iOS 7 mehr Platz vorhanden ist. Und ich habe herausgefunden, dass dies ungefähr 10 Punkte mehr sind. Normalerweise verwende ich negative Leerzeichen, wenn ich LeftBarItemButtonam Rand beginnen möchte . Dies kann auch für Sie nützlich sein.

UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];

negativeSpacer.width = -16; // it was -6 in iOS 6

[self.navigationItem setLeftBarButtonItems:@[negativeSpacer, requiredButton]; /* this will be the button which you actually need */] animated:NO];
Adnan Aftab
quelle
4
Es funktioniert wirklich in iOS 7, da ich dies gerade in einigen Projekten verwende ... es gibt Unterschiede im Punktesystem, also müssen Sie sich darum kümmern ...
Adnan Aftab
10
Es funktioniert nicht, wenn Sie [NSArray arrayWithObjects: requiredButton, negativeSpacer] ausführen. Achten Sie auf die Reihenfolge.
Mert Buran
3
Funktioniert hervorragend und beachten Sie, dass für rightBarButtonItems der Spacer das erste Element im Array sein muss, wenn Sie den rechten Rand ändern möchten
Leonaka
1
@C_X für iPhone 6, der Rand von -16 scheint nicht zu funktionieren. -20 scheint richtig zu sein. Irgendeine Idee, wie wir dies auf allen iPhone-Geräten zum Laufen bringen können?
Vignesh PT
1
@TheRohanSanap - Eine positive Breite wäre ein Abstandshalter, der den Leerraum vor dem ersten visuellen Element erhöht . Dieser Trick mit einer negativen Breite verringert den leeren Raum.
ToolmakerSteve
23

Basierend auf @C_X seiner Antwort habe ich eine Kategorie erstellt, die das UIBarButtonItem basierend auf der iOS-Version des aktuellen Geräts hinzufügt und positioniert.

// UINavigationItem+Additions.h
@interface UINavigationItem (Additions)
- (void)addLeftBarButtonItem:(UIBarButtonItem *)leftBarButtonItem;
- (void)addRightBarButtonItem:(UIBarButtonItem *)rightBarButtonItem;
@end

// UINavigationItem+Additions.m
@implementation UINavigationItem (Additions)

- (void)addLeftBarButtonItem:(UIBarButtonItem *)leftBarButtonItem
{
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        // Add a negative spacer on iOS >= 7.0
        UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
                              target:nil action:nil];
        negativeSpacer.width = -10;
        [self setLeftBarButtonItems:[NSArray arrayWithObjects:negativeSpacer, leftBarButtonItem, nil]];
    } else {
        // Just set the UIBarButtonItem as you would normally
        [self setLeftBarButtonItem:leftBarButtonItem];
    }
}

- (void)addRightBarButtonItem:(UIBarButtonItem *)rightBarButtonItem
{
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        // Add a negative spacer on iOS >= 7.0
        UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc]
                                       initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
                                       target:nil action:nil];
        negativeSpacer.width = -10;
        [self setRightBarButtonItems:[NSArray arrayWithObjects:negativeSpacer, rightBarButtonItem, nil]];
    } else {
        // Just set the UIBarButtonItem as you would normally
        [self setRightBarButtonItem:rightBarButtonItem];
    }
}

@end

In Ihrem View Controller können Sie jetzt [self.navigationItem addLeftBarButtonItem:leftBarButtonItem];und verwenden[self.navigationItem addRightBarButtonItem:rightBarButtonItem];

Ich habe auch versucht, Unterklassen zu erstellen UIButtonund zu überschreiben, -alignmentRectInsetsaber dies gab mir Probleme mit Übergängen zwischen Ansichten.

stinken
quelle
10

Für Swift 2.0 war dies meine Lösung, um den folgenden Effekt zu erzielen ...

(Die tatsächlichen Werte können je nach Situation unterschiedlich sein.)

Geben Sie hier die Bildbeschreibung ein

let captureButton = UIButton()
captureButton.setTitle("CAPTURE DETAILS", forState: .Normal)
captureButton.frame = CGRectMake(0, 0, 200, 95)
captureButton.addTarget(self, action: Selector("showCaptureDetailsForm:"), forControlEvents: .TouchUpInside) // *** See update below for Swift 2.2 syntax
captureButton.setBackgroundImage(UIImage(named: "blueTopRight"), forState: .Normal)
        
let rightBarButton = UIBarButtonItem()
rightBarButton.customView = captureButton        
        
let negativeSpacer = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FixedSpace, target: nil, action: nil)
negativeSpacer.width = -25;
        
self.navigationItem.setRightBarButtonItems([negativeSpacer, rightBarButton ], animated: false)

Swift 2.2 UPDATE:

Für Swift 2.2 hat sich die action: SelectorMethode geändert und sollte wie folgt eingegeben werden

captureButton.addTarget(self, action: #selector(YourViewController.showCaptureDetailsForm(_:)), forControlEvents: .TouchUpInside)

Simon
quelle
9

Dies ist meine Lösung für Swift 3.0:

rightBtn.imageInsets = UIEdgeInsets(top: 0, left: -13.0, bottom: 0, right: 13.0) 
self.navigationItem.rightBarButtonItem = rightBtn
Tuandapen
quelle
6

Um diesen Fehler zu beheben, müssen Sie eine Unterklasse UIButtonerstellen, damit Sie diese überschreiben können alignmentRectInsets. Nach meinen Tests müssen Sie je nach Tastenposition a UIEdgeInsetsmit einem positiven Versatz nach rechts oder einem positiven Versatz nach links zurückgeben. Diese Zahlen ergeben für mich keinen Sinn (mindestens eine davon sollte nach gesundem Menschenverstand negativ sein), aber genau das funktioniert:

- (UIEdgeInsets)alignmentRectInsets {
    UIEdgeInsets insets;
    if (IF_ITS_A_LEFT_BUTTON) {
        insets = UIEdgeInsetsMake(0, 9.0f, 0, 0);
    } 
    else { // IF_ITS_A_RIGHT_BUTTON
        insets = UIEdgeInsetsMake(0, 0, 0, 9.0f);
    }
    return insets;
}

Besonderer Dank geht an @zev für den Vorschlag, mich anzupassen alignmentRectInsets.

jaredsinclair
quelle
Danke für die Antwort. Es ist zwar eine gute Lösung, aber ich habe die Antwort @C_X vorgezogen, weil ich gerade versuche, eine Unterklassifizierung zu vermeiden.
Salman Zaidi
Dies führte zu merkwürdigen Verschiebungen der Schaltflächen während der Animationen in iOS 6, sie begannen an der falschen Stelle und wurden verschoben, um den Einsätzen zu entsprechen, nachdem die Animation abgeschlossen war.
Chris Wagner
Ich wäre nicht überrascht. Der obige Code wird nur benötigt, um ein Layout im iOS 6-Stil für iOS 7-Builds zu erhalten.
Jaredsinclair
Schnelle Lösung, gute Arbeit. Für iOS 9 müssen Sie jedoch die nicht eingestellten
A-Majeed
5

Dem Beispiel von smek folgend, habe ich eine Kategorie erstellt, diese jedoch geändert, um Abwärtskompatibilität und nicht Vorwärtskompatibilität zu gewährleisten. Ich richte alles so ein, wie es in iOS 7 funktioniert, und wenn der Benutzer etwas niedrigeres ausführt, fange ich an, mich mit Dingen zu beschäftigen.

@interface UINavigationItem (BarButtonItemSpacingSupport)

- (void)addLeftBarButtonItem:(UIBarButtonItem *)leftBarButtonItem;
- (void)addRightBarButtonItem:(UIBarButtonItem *)rightBarButtonItem;

@end

@implementation UINavigationItem (BarButtonItemSpacingSupport)

- (void)addLeftBarButtonItem:(UIBarButtonItem *)leftBarButtonItem
{
    if (SYSTEM_VERSION_LESS_THAN(@"7.0")) {
        // Add a spacer on when running lower than iOS 7.0
        UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
                                                                                        target:nil action:nil];
        negativeSpacer.width = 10;
        [self setLeftBarButtonItems:[NSArray arrayWithObjects:negativeSpacer, leftBarButtonItem, nil]];
    } else {
        // Just set the UIBarButtonItem as you would normally
        [self setLeftBarButtonItem:leftBarButtonItem];
    }
}

- (void)addRightBarButtonItem:(UIBarButtonItem *)rightBarButtonItem
{
    if (SYSTEM_VERSION_LESS_THAN(@"7.0")) {
        // Add a spacer on when running lower than iOS 7.0
        UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc]
                                           initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
                                           target:nil action:nil];
        negativeSpacer.width = 10;
        [self setRightBarButtonItems:[NSArray arrayWithObjects:negativeSpacer, rightBarButtonItem, nil]];
    } else {
        // Just set the UIBarButtonItem as you would normally
        [self setRightBarButtonItem:rightBarButtonItem];
    }
}

@end

Und um dies global zu erhalten, habe ich eine dünne UIViewControllerUnterklasse, von der alle meine View-Controller erben.

@interface INFViewController : UIViewController

@end

@implementation INFViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    if (SYSTEM_VERSION_LESS_THAN(@"7.0")) {
        [self setupNavBarForPreIOS7Support];
    }
}

- (void)setupNavBarForPreIOS7Support {
    if (self.navigationController) {
        UINavigationItem *navigationItem = self.navigationItem;
        UIBarButtonItem *leftItem = navigationItem.leftBarButtonItem;
        UIBarButtonItem *rightItem = navigationItem.rightBarButtonItem;

        if (leftItem) {
            [navigationItem addLeftBarButtonItem:leftItem];
        }

        if (rightItem) {
            [navigationItem addRightBarButtonItem:rightItem];
        }
    }
}

@end

Mir ist klar, dass ich die Betriebssystemversion zweimal überprüfe (immer INFViewControllerwieder in der Kategorie). Ich habe sie in der Kategorie belassen, falls ich sie irgendwo im Projekt einmalig verwenden möchte.

Chris Wagner
quelle
5

für schnell können Sie dies tun

var negativeSpace:UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FixedSpace, target: nil, action: nil)
negativeSpace.width = -17.0
self.navigationItem.rightBarButtonItems = [negativeSpace, requiredButton /* this will be the button which you actually need */]
reza pahlevi
quelle
5
As of iOS 11 wont accept negative space width, in order to align the bar button items to the margin, I have used the below code.

 override func viewWillLayoutSubviews() {
                super.viewWillLayoutSubviews()
                for view in (self.navigationController?.navigationBar.subviews)! {
                    view.layoutMargins = UIEdgeInsets.zero
                }
            }
vinny
quelle
2
Diese Methode wird mit Verzögerung aufgerufen
Orium
Dies ist die genaue Lösung, um dies zu tun, negativer Speicherplatz funktioniert nicht von iOS 11
Rafiqul Hasan
4

Swift 3:

let negativeSpacer:UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.fixedSpace, target: nil, action: nil)
        negativeSpacer.width = -10
self.navigationItem.leftBarButtonItems = [negativeSpacer, yourBarButtonItem]
Dvole
quelle
2

Swift 3.1

So geben Sie dem Element der linken Leistenschaltfläche einen negativen Platz:

    let backButton = UIButton.init(type: .custom)
    backButton.frame = CGRect.init(x: 0, y: 0, width: 40, height: 40)
    // negative space
    backButton.contentEdgeInsets = UIEdgeInsets(top: 0, left: -44.0, bottom: 0, right: 0)
    backButton.setImage(Ionicons.iosArrowBack.image(30, color: UIColor(hex: 0xFD6250)), for: .normal)
    backButton.addTarget(self, action: #selector(InviteVC.goBack), for: .touchUpInside)   
    // set back button
    self.navigationItem.leftBarButtonIteUIBarButtonItem.init(customView: backButton) 

rp2701
quelle
1

Negativer Speicherplatz funktioniert unter iOS 11 nicht

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    // to remove navigation bar extra margin
    for view in (self.navigationController?.navigationBar.subviews)! {
        view.layoutMargins = UIEdgeInsets.zero
    }
}

Der obige Code entfernt den Rand von beiden Seiten leftBarButtonItem und RightBarButtonItem. Wenn Sie einen zusätzlichen Rand hinzufügen müssen (nach dem Entfernen des Randes), fügen Sie den folgenden Code hinzu

    let rightButton = UIButton(frame: CGRect(x: 0, y: 0, width: 17, height: 20))
    rightButton.setImage(UIImage(named: "ic_cart"), for: .normal)

    let rightBarButtomItem = UIBarButtonItem(customView: rightButton)

    let spacer = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.fixedSpace, target: nil, action: nil)
    spacer.width = 28 //This will add extra margin on right side
    navigationItem.rightBarButtonItems = [spacer,rightBarButtomItem]
Rafiqul Hasan
quelle
'Client-Fehler beim Versuch, die Layout-Ränder einer privaten Ansicht zu ändern'
Vlad Pulichev
0

Ich glaube, Sie müssen eine benutzerdefinierte Schaltfläche mit einer UIButtonUnterklasse verwenden und in Ihrer Unterklasse überschreiben -alignmentRectInsets. Ich habe vergessen, ob Sie einen positiven oder negativen Wert für die entsprechende Flanke benötigen, damit sie richtig verschoben wird. Wenn jedoch eine nicht funktioniert, versuchen Sie es mit der anderen.

Zev Eisenberg
quelle
0

arbeitete für mich

rightBarButton.customView? .transform = CGAffineTransform (ÜbersetzungX: 10, y: 0)

Junkie
quelle
-1

Gute Entscheidung, vielen Dank! Ich musste nur zwei Elemente auf der linken Seite des Navigationsheaders hinzufügen. Das ist meine Lösung:

  // Settings Button
  // This trick correct spacing between two left buttons
  UIBarButtonItem *settingsButtonItem = [[UIBarButtonItem alloc] init];
  UIView *settingsButtonItemView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 22.0, 22.0)];
  settingsButtonItem.customView = settingsButtonItemView;
  UIButton *settingsButton = [UIButton buttonWithType:UIButtonTypeSystem];
  settingsButton.frame = settingsButtonItemView.frame;
  [settingsButton setImage:[UIImage imageNamed:@"settings"] forState:UIControlStateNormal];
  settingsButton.tintColor = [[[[UIApplication sharedApplication] delegate] window] tintColor];
  [settingsButton addTarget:self action:@selector(showSettings:) forControlEvents:UIControlEventTouchDown];
  [settingsButtonItemView addSubview:settingsButton];

  // Star Button
  UIBarButtonItem *starButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"star_gray"] style:UIBarButtonItemStyleBordered target:self action:@selector(showStarred)];
  starButtonItem.width = 22.0;
  NSLog(@"%f", starButtonItem.width);

  // Negative Spacer
  // It shifts star button to the left
  UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
  negativeSpacer.width = -10.0;

  NSArray *leftNavigtaionBarButtonItems = @[negativeSpacer, starButtonItem, settingsButtonItem];
  [self.navigationItem setLeftBarButtonItems:leftNavigtaionBarButtonItems];
Igor Leonovich
quelle