Navigationsleiste rechtsbaritem Bild-Button-Fehler iOS 11

101

Dieser Code funktioniert in ios10 einwandfrei. Ich bekomme mein Etikett und eine Bildschaltfläche, die das Benutzerfoto-Profil ist, kreisförmig rund .. ok. aber wenn ich xcode 9 ios11 simulator laufen lasse, bekomme ich es gestreckt. Der Schaltflächenrahmen muss 32x32 sein, wenn ich die Sim überprüfe und die Ansicht erhalte und xcode anweise, die Ansicht zu beschreiben, die ich als 170x32 oder so etwas ausgeben lasse.

Hier ist mein Code.

let labelbutton = UIButton( type: .system)
    labelbutton.addTarget(self, action:#selector(self.toLogin(_:)), for: .touchUpInside)
    labelbutton.setTitleColor(UIColor.white, for: .normal)
    labelbutton.contentHorizontalAlignment = .right
    labelbutton.titleLabel?.font = UIFont.systemFont(ofSize: 18.00)



    let button = UIButton(type: .custom)
     button.addTarget(self, action:#selector(self.toLogin(_:)), for: .touchUpInside)
     button.frame = CGRect(x: 0, y: 0, width: 32, height: 32)
     button.setTitleColor(UIColor.white, for: .normal)
     button.setTitleColor(UIColor.white, for: .highlighted)


    var buttomItem : UIBarButtonItem = UIBarButtonItem()
    buttomItem.customView = button
    buttomItem.target = self
    buttomItem.action = "ToLogin"

    var labelItem : UIBarButtonItem = UIBarButtonItem()
    labelItem.customView = labelbutton
    labelItem.target = self
    labelItem.action = "ToLogin"


    if let user = PFUser.current() {
        print("LOGIN : checkiando si existe usuario ")
            labelbutton.setTitle(USERNAME, for: UIControlState.normal)
            labelbutton.sizeToFit()

        if(user["profile_photo_url"] != nil) {
            print(" ENCONTRO PROFILE PHOTO URL NOT NIL Y ES \(user["profile_photo_url"])")
            let photoURL = user["profile_photo_url"] as! String
            let a = LoginService.sharedInstance
            a.downloadImage(url: photoURL, complete: { (complete) in

                if (complete) {

                    button.setImage(LoginService.sharedInstance.profile_photo! , for: UIControlState.normal)

                    button.layer.cornerRadius = 0.5 * button.bounds.size.width
                   // button.imageView!.contentMode = .scaleAspectFit
                   // button.imageView!.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
                    //button.imageView!.contentMode = .scaleAspectFit
                    //button.imageView!.clipsToBounds = true
                    //button.imageView!.layer.cornerRadius = 60
                    button.clipsToBounds = true
                    self.NavigationItem.rightBarButtonItems = [buttomItem,labelItem]
                }


            })
        } else {
                self.NavigationItem.rightBarButtonItem = labelItem

        }
            print(" EL FRAME DEL BUTTON ES \(button.frame)")

    } else {

        labelbutton.setTitle("Login", for: UIControlState.normal)
        labelbutton.sizeToFit()
        self.NavigationItem.rightBarButtonItem = labelItem

    }

Geben Sie hier die Bildbeschreibung ein

Lorenzo Gonzalez
quelle
Haben Sie die Stapelansicht in der Navigationsleiste verwendet?
Vlad Khambir
@ V.Khambir Nop ...: /
Lorenzo Gonzalez
Ist dieser Fehlerbericht irgendwo?
Edu
iOS 11 verwendet AutoLayout zum Layouten von Navigationselementen. UIButtonUIBarButtonItembutton.imageEdgeInsets = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: -20)
Wenn

Antworten:

188

Grund

Das Problem tritt auf, weil ab ios 11 UIBarButtonItemAutolayout verwendet wird, anstatt sich mit Frames zu befassen.

Lösung

Wenn Sie Xcode 9 verwenden, sollten Sie für diese Bildschaltfläche eine Breitenbeschränkung hinzufügen.

 button.widthAnchor.constraint(equalToConstant: 32.0).isActive = true
 button.heightAnchor.constraint(equalToConstant: 32.0).isActive = true

PS

buttonist nicht UIBarButtonItem, es ist UIButtondrinnen UIBarButtonItem. Sie sollten die Einschränkung nicht für UIBarButtonItem, sondern für darin enthaltene Elemente festlegen .

Vlad Khambir
quelle
3
@ V.Khambir jetzt bekomme ich dieses Problem. Aber mit der gleichen Lösung mit xcode 9, und wenn ich in ios 1 Gerät laufen, ist es in Ordnung .. Aber wenn ich in ios 10 Version Gerät laufen .. meine Balkenschaltfläche Bilder r überhaupt nicht angezeigt. Wie kann ich das für alle Versionen beheben? Ich habe das Gerät von beiden iOS 11, iOS 10 eingecheckt. Wird nur in der iOS 1-Version angezeigt. in ios 10 zeigt das bild überhaupt nicht
david
@spikesa, es sollte auf beiden iOS-Versionen funktionieren, wahrscheinlich haben Sie falsche Einschränkungen festgelegt.
Vlad Khambir
@ V.Khambir Wert vom Typ 'UIBarButtonItem' hat kein Mitglied 'widthAnchor' in Xcode 9 innerhalb einer if #available (iOS 11.0, *) Bedingung?
Ryan Brodie
1
@jped hast du eine Lösung dafür gefunden? Es funktioniert auch nicht für mich unter iOS 10 mit Xcode 9
Swalkner
1
Toll. Ich muss diese bahnbrechenden Veränderungen lieben. Hat Apple eine Liste dieser Arten von Änderungen auf einer Seite oder in Versionshinweisen irgendwo dokumentiert?
GONeale
53

Vielen Dank für Ihren Beitrag! ihr habt recht! Für xcode9 ios11 müssen Sie eine Einschränkung festlegen.

 let widthConstraint = button.widthAnchor.constraint(equalToConstant: 32)
 let heightConstraint = button.heightAnchor.constraint(equalToConstant: 32)
 heightConstraint.isActive = true
 widthConstraint.isActive = true
Lorenzo Gonzalez
quelle
1
Das hat auch bei mir funktioniert, aber kann jemand erklären, warum dies für iOS 11 notwendig ist, als es noch nie zuvor war?
Stonedauwg
9
UINavigationBar gestaltet jetzt seine Unteransichten mit Auto Layout
mangerlahn
2
Machen Sie nicht den gleichen Fehler, den ich gemacht habe: Ich habe ausgeschaltet translatesAutoresizingMaskIntoConstraintsund später herausgefunden, dass iOS 9 völlig kaputt war (aber auf iOS 10 und 11 gut aussah)
xaphod
2
Value of type 'UIBarButtonItem' has no member 'widthAnchor'in Xcode 9 innerhalb einer if #available(iOS 11.0, *)Bedingung?
Ryan Brodie
@ Lorenzo-Gonzalez Wie hast du es geschafft? Ich stecke fest.
Alessandro Lucarini
18

Der objektive C-Code ist jetzt veraltet. Für den Benutzer, der Objective C-Projekte in iOS 11 erstellen / warten muss, ist die folgende Übersetzung von Swift (Antwort von Karoly Nyisztor) nach Objective C hilfreich.

//  UIView+Navbar.h

#import <UIKit/UIKit.h>

@interface UIView (Navbar)

- (void)applyNavBarConstraints:(CGFloat)width height:(CGFloat)height;

@end

//----------

//  UIView+Navbar.m

#import "UIView+Navbar.h"

@implementation UIView (Navbar)

- (void)applyNavBarConstraints:(CGFloat)width height:(CGFloat)height
{
    if (width == 0 || height == 0) {
        return;
    }

    NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:height];
    NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:width];
    [heightConstraint setActive:TRUE];
    [widthConstraint setActive:TRUE];
}

//----------

// Usage :-
[button applyNavBarConstraints:33 height:33];
SHS
quelle
Cool. Eigentlich brauchte ich auch die Objective-C-Version. Übrigens ändert Xcode 9 die Größe der Navigationsleistenelemente im Storyboard nach dem Zufallsprinzip. Ich muss es jedes Mal überprüfen, bevor ich meine Änderungen weitergebe. Hoffe, dass dies irgendwann bald behoben wird.
Karoly Nyisztor
du bist mein Held, weil ich altes Projekt mit Ziel-c umgestalten muss.
Marosdee Uma
18

Nun, das neue barButtonItemverwendet Autolayout, anstatt sich mit Frames zu befassen.

Das Bild, das Sie der Schaltfläche hinzugefügt haben, ist größer als die Schaltfläche selbst. Aus diesem Grund wurde die Schaltfläche selbst auf die Bildgröße gedehnt. Sie müssen die Größe des Bilds an die Größe der gewünschten Schaltfläche anpassen, bevor Sie es der Schaltfläche hinzufügen.

Ahmad Farrag
quelle
14

Ich habe eine winzige Erweiterung zum Festlegen der Einschränkungen für Navigationsleistenelemente geschrieben:

import UIKit

extension UIView {
    func applyNavBarConstraints(size: (width: CGFloat, height: CGFloat)) {
    let widthConstraint = self.widthAnchor.constraint(equalToConstant: size.width)
    let heightConstraint = self.heightAnchor.constraint(equalToConstant: size.height)
    heightConstraint.isActive = true
    widthConstraint.isActive = true
  }
}

// Usage
button.applyNavBarConstraints(size: (width: 33, height: 33))
Karoly Nyisztor
quelle
Großartige Idee! Angewandt UIButtonfunktioniert das sehr gut.
Alessandro Ornano
12

Ich habe dies objektiv mit folgenden Zeilen gemacht:

NSLayoutConstraint * widthConstraint = [customButton.widthAnchor constraintEqualToConstant:40];
NSLayoutConstraint * HeightConstraint =[customButton.heightAnchor constraintEqualToConstant:40];
[widthConstraint setActive:YES];
[HeightConstraint setActive:YES];

UIBarButtonItem* customBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:customButton];
self.navigationItem.leftBarButtonItem = customBarButtonItem;

Danke Viel Spaß beim Codieren !!

Aleem
quelle
7

Was ich getan habe?

In meiner App habe ich ein Profilbild in der Navigationsleiste unter dem Element "RightBarButton" hinzugefügt. vor iOS 11 funktionierte es gut und wurde ordnungsgemäß angezeigt, aber wenn es auf iOS 11 aktualisiert wurde, änderte sich das Verhalten wie Schlag

Geben Sie hier die Bildbeschreibung ein

Also habe ich UIViewim rechten Schaltflächenelement hinzugefügt und UIButtonals Unteransicht von UIView? Wie unten,

Geben Sie hier die Bildbeschreibung ein

Und ich setze Höhen- und Breitenbeschränkungen von UIButton.

Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein

Und mein Problem ist gelöst. Vergessen Sie nicht, die UIViewHintergrundfarbe als klare Farbe festzulegen.

HINWEIS: Wenn Ihre Schaltfläche nicht funktioniert, überprüfen Sie, ob Ihre UIView'sHöhe möglicherweise 0 ist. Hier sollten Sie die Höhe 0 auf 44 ändern oder was auch immer Sie möchten. Und auch clipToBound = true, jetzt können Sie die Position Ihres Knopfes einstellen und es wird gut funktionieren.

iPatel
quelle
Dies funktioniert, die Schaltfläche funktioniert jedoch nicht mehr, wenn Sie sie einer Ansicht hinzufügen. Irgendwelche Tipps?
Eonist
@GitSync Überprüfen Sie die Höhe Ihrer Ansicht auf 0, ändern Sie sie auf 44 oder was auch immer Sie möchten, und machen Sie clipToBound = true und setzen Sie dann die Schaltfläche.
iPatel
1
Beeindruckend. funktioniert! Pro Tipp: Verwendung .pdf Vermögenswerte statt .png
eonist
ist die Containeransicht notwendig? Kann ich UIButton nicht einfach direkt verwenden?
Igrek
5

Das Ändern von widthAnchor/ heightAnchorfunktioniert nur auf iOS 11+ Geräten. Für iOS 10-Geräte müssen Sie die Frames auf klassische Weise manuell ändern. Die Sache ist, dass keiner der beiden Ansätze für beide Versionen funktioniert, so dass Sie sich je nach Laufzeitversion unbedingt programmgesteuert abwechseln müssen, wie unten:

if #available(iOS 11.0, *)
{
   button.widthAnchor.constraint(equalToConstant: 32.0).isActive = true
   button.heightAnchor.constraint(equalToConstant: 32.0).isActive = true
}else
{
   var frame = button.frame
   frame.size.width = 32.0
   frame.size.height = 32.0
   button.frame = frame
}
Malloc
quelle
1
Danke für den iOS 10 Tipp! Ich hatte das iOS 11-Update, konnte es aber für iOS 10 nicht herausfinden.
Clifton Labrum
3

Obwohl iOS 11 Autolayout für die Navigationsleiste verwendet, ist es möglich, dass es traditionell zum Festlegen von Frames funktioniert. Hier ist mein Code, der für ios11 und ios10 oder älter funktioniert:

func barItemWithView(view: UIView, rect: CGRect) -> UIBarButtonItem {
    let container = UIView(frame: rect)
    container.addSubview(view)
    view.frame = rect
    return UIBarButtonItem(customView: container)
}

und so setzt sich das Barelement zusammen:

    let btn = UIButton()
    btn.setImage(image.withRenderingMode(.alwaysTemplate), for: .normal)
    btn.tintColor = tint
    btn.imageView?.contentMode = .scaleAspectFit
    let barItem = barItemWithView(view: btn, rect: CGRect(x: 0, y: 0, width: 22, height: 22))
    return barItem
Leszek Zarna
quelle
3

Das programmgesteuerte Setzen von Einschränkungen hat bei Benutzern mit iOS 11.X für mich funktioniert. Die Balkentaste wurde jedoch für Benutzer mit iOS 10.X immer noch gestreckt. Ich denke, die AppStore-Rezensenten haben iOS 11.X ausgeführt, daher konnte ich mein Problem nicht identifizieren, sodass meine App zum Verkauf bereit war und hochgeladen wurde.

Meine Lösung bestand darin, die Abmessungen meines Bildes in einer anderen Software einfach auf 30 x 30 zu ändern (die vorherige Bildabmessung betrug 120 x 120).

Erik Nguyen
quelle
1
Da die Navigationsleiste in ios10 automatisch angepasst wird und ios11 automatisch angepasst wird, müssen Sie mit if #available (iOS 11, *) {}
Paulo Sigales
Ich habe die neuen Änderungen
durchgearbeitet
Tolle, einfache Antwort. Danke dir. Nichts anderes funktionierte und es machte mich verrückt.
Bretagne
0

Ich hatte auch Erfolg bei der Implementierung intrinsicContentSize, um eine geeignete Größe für jede benutzerdefinierte UIView-Unterklasse zurückzugeben, die ich als benutzerdefinierte Ansicht verwenden möchte.

Chris
quelle
0

Ich habe ein Balkenschaltflächenelement erstellt und es dann zur Navigationsleiste hinzugefügt.

    private var addItem: UIBarButtonItem = {
        let addImage = UIImage(named: "add")
        let addButton = UIButton(type: UIButton.ButtonType.custom)
        addButton.setBackgroundImage(addImage, for: UIControl.State())
        addButton.frame = CGRect(x: 0, y: 0, width: (addImage?.size.width)!, height: (addImage?.size.height)!)
        let addItem = UIBarButtonItem(customView: addButton)
        return addItem
    }()

 private var contactsItem: UIBarButtonItem = {
        let contactsImage = UIImage(named: "contacts")
        let contactsButton = UIButton(type: UIButton.ButtonType.custom)
        contactsButton.setBackgroundImage(contactsImage, for: UIControl.State())
        contactsButton.frame = CGRect(x: 0, y: 0, width: (contactsImage?.size.width)!, height: (contactsImage?.size.height)!)
        let contactsItem = UIBarButtonItem(customView: contactsButton)
        return contactsItem
    }()

In viewDidLoad ()

let spacerBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.fixedSpace, target: nil, action: nil)
        spacerBarButtonItem.width = 11
        navigationItem.rightBarButtonItems = [addItem, spacerBarButtonItem, contactsItem]

Hier habe ich das Bild von 28x28.

vinny
quelle