web-dev-qa-db-de.com

Navigationsleiste rechts Bild-Button Bug iOS 11

Dieser Code funktioniert in ios10. Ich bekomme mein Etikett und einen Bildknopf, der das Benutzerfotoprofil ist, kreisrund .. ok. aber wenn ich xcode 9 ios11 simulator laufen lasse, bekomme ich es ausgestreckt. Der Schaltflächenrahmen muss 32x32 sein, wenn Sie auf der Sim nachsehen und die Ansicht abrufen und xcode angeben, um die Ansicht zu beschreiben. Ich erhalte die Ausgabe als 170x32 oder so ähnlich.

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

    }

enter image description here

98

Grund

Das Problem tritt auf, weil ab ios 11 UIBarButtonItem Autolayout verwendet, 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

button ist nicht UIBarButtonItem, sondern UIButton in UIBarButtonItem. Sie sollten die Einschränkung nicht für UIBarButtonItem, sondern für darin enthaltene Elemente festlegen.

176
Vlad Khambir

Vielen Dank für Ihren Beitrag! ihr seid richtig !. Für xcode9 ios11 müssen Sie eine Einschränkung setzen.

 let widthConstraint = button.widthAnchor.constraint(equalToConstant: 32)
 let heightConstraint = button.heightAnchor.constraint(equalToConstant: 32)
 heightConstraint.isActive = true
 widthConstraint.isActive = true
53

Nun, das neue barButtonItem verwendet Autolayout anstelle von Frames.

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

18
Ahmad Farrag

Der objektive C-Code ist jetzt veraltet. Aber für den Benutzer, der Objective C-Projekte in iOS 11 erstellen/warten muss, ist folgende Übersetzung von Swift (Karoly Nyisztor answer) zu 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];
18
SHS

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))
14
Karoly Nyisztor

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;

Vielen Dank Happy Coding!

12
Aleem

Was ich getan habe?

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

enter image description here

Also habe ich UIView im rechten Schaltflächenelement hinzugefügt und UIButton als Unteransicht von UIView festgelegt? Wie unten,

enter image description here

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

enter image description hereenter image description here

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

HINWEIS: Wenn Ihre Schaltfläche nicht funktioniert, überprüfen Sie Ihre UIView's height könnte sein 0 hier sollten Sie die Höhe 0 auf ändern 44 oder was auch immer Sie wollen. Und mache auch clipToBound = true, Jetzt können Sie die Position Ihrer Taste festlegen und es wird gut funktionieren.

7
iPatel

Das Ändern von widthAnchor/heightAnchor funktioniert nur auf Geräten mit iOS 11+. Für iOS 10-Geräte müssen Sie die klassischen Methoden zum manuellen Ändern der Frames anwenden. Die Sache ist, dass keiner der beiden Ansätze für beide Versionen funktioniert. Sie müssen also abhängig von der Laufzeitversion wie folgt programmgesteuert abwechseln:

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

Obwohl iOS 11 Autolayout für die Navigationsleiste verwendet, ist es möglich, das herkömmliche Einstellen von Frames zu ermöglichen. Hier ist mein Code für ios11 und ios10 oder älter:

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
3
Leszek Zarna

Das programmgesteuerte Setzen von Einschränkungen hat bei mir für Benutzer mit iOS 11.X funktioniert. Allerdings war die Leistenschaltfläche für Benutzer mit iOS 10.X weiterhin gedehnt. Ich denke, die AppStore-Rezensenten haben iOS 11.X ausgeführt. Daher konnte ich mein Problem nicht identifizieren, sodass meine App für den Verkauf vorbereitet und hochgeladen wurde ..

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

3
Erik Nguyen

Ich habe ein Leistenschaltflächenelement erstellt und es dann der 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.

0
vinny

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

0
Chris