web-dev-qa-db-fra.com

barre de navigation rightbaritem bug bouton image iOS 11

Ce code fonctionne bien dans ios10. Je reçois mon étiquette et un bouton d’image qui correspond au profil de la photo de l’utilisateur, circulaire. ok. mais lorsque je lance xcode 9 ios11 simulator, je l’ai étouffé. le cadre du bouton doit être 32x32, lors de la vérification de la sim et de l'affichage de la vue et de l'indication de xcode pour décrire la vue, la sortie est 170x32 ou quelque chose comme ça.

heres mon 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
lorenzo gonzalez

Raison

Le problème apparaît car, à partir de ios 11, UIBarButtonItem utilise autolayout au lieu de traiter les images.

Solution

Vous devez ajouter une contrainte de largeur pour ce bouton image si vous utilisez Xcode 9.

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

PS

button n'est pas UIBarButtonItem, c'est UIButton à l'intérieur de UIBarButtonItem. Vous ne devez pas définir la contrainte pour UIBarButtonItem, mais pour les éléments qu’elle contient.

176
Vlad Khambir

Merci à tous pour votre contribution! vous avez raison! pour xcode9 ios11, vous devez appliquer une contrainte.

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

Eh bien, la nouvelle barButtonItem utilise autolayout au lieu de traiter avec des cadres.

L'image que vous ajoutiez au bouton est plus grande que la taille du bouton lui-même. C'est pourquoi le bouton lui-même s'est étiré à la taille de l'image. Vous devez redimensionner l'image pour qu'elle corresponde à la taille du bouton souhaité avant de l'ajouter au bouton.

18
Ahmad Farrag

Le code Objective C est obsolète maintenant. Mais pour l'utilisateur qui doit construire/maintenir des projets Objective C dans iOS 11, la traduction suivante de Swift (réponse de Karoly Nyisztor) à Objective C est utile.

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

J'ai écrit une petite extension pour définir les contraintes sur les éléments de la barre de navigation:

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

J'ai fait ceci en objectif en utilisant les lignes suivantes:

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;

Merci codage heureux !!

12
Aleem

Ce que j'ai fait?

Dans mon application, j'ai ajouté une image de profil sur navigationBar à l'élément rightBarButton. avant iOS 11, il fonctionnait bien et s’affiche correctement, mais lorsqu’il est mis à jour vers iOS 11, le comportement change comme un coup dur.

enter image description here

J'ai donc ajouté UIView dans l'élément du bouton de droite et défini UIButton comme sous-vue de UIView? Comme ci-dessous,

enter image description here

Et je règle les contraintes de hauteur et de largeur de UIButton.

enter image description hereenter image description here

Et mon problème est résolu. N'oubliez pas de définir la couleur d'arrière-plan de UIView comme claire .

REMARQUE: Si votre bouton ne fonctionnera pas, vérifiez que votre UIView's hauteur correspond à sa 0 ici vous devez changer la hauteur 0 en 44 ou ce que vous voulez. Et aussi, faites clipToBound = true, vous pouvez maintenant régler la position de votre bouton et cela fonctionnera bien.

7
iPatel

Changer la widthAnchor/heightAnchor ne fonctionnera que sur les appareils iOS 11+. Pour les appareils iOS 10, vous devez utiliser la méthode classique de modification manuelle des images. Le fait est qu'aucune des deux approches ne fonctionne pour les deux versions, vous devez donc impérativement alterner par programme en fonction de la version d'exécution, comme ci-dessous:

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

Même si iOS 11 utilise Autolayout pour la barre de navigation, il est possible de le faire fonctionner traditionnellement en définissant des cadres. Voici mon code fonctionnant pour ios11 et ios10 ou plus ancien:

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

et voici comment se compose l'article de barre:

    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

Mettre les contraintes par programme a fonctionné pour moi pour les utilisateurs de iOS 11.X. Cependant, le bouton de barre était toujours étendu pour les utilisateurs de iOS 10.X. Je suppose que les relecteurs de l'AppStore fonctionnaient sous iOS 11.X, donc je ne pouvais pas identifier mon problème, donc mon application était prête pour la vente et téléchargée. ..

Ma solution consistait simplement à modifier les dimensions de mon image en 30x30 dans un autre logiciel (les dimensions de l'image précédente étaient 120x120).

3
Erik Nguyen

J'ai créé un élément de bouton de barre, puis je l'ai ajouté à la barre de navigation.

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

Dans viewDidLoad ()

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

Ici, j'ai l'image de 28x28.

0
vinny

J'ai également eu du succès en implémentant intrinsicContentSize pour renvoyer une taille appropriée pour toute sous-classe UIView personnalisée que je compte utiliser comme customView.

0
Chris