101 votes

Barre de navigation rightbaritem image-button bug iOS 11

Ce code fonctionne correctement sur ios10. J'obtiens mon étiquette et un bouton image représentant la photo de profil de l'utilisateur, de forme ronde.. d'accord. mais lorsque je lance le simulateur xcode 9 ios11, l'image est étirée. Le cadre du bouton doit être de 32x32, à la vérification sur le simulateur et en demandant à xcode de décrire la vue, j'obtiens une sortie de 170x32 ou quelque chose du genre.

Voici 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 : vérification de l'existence de l'utilisateur ")
            labelbutton.setTitle(USERNAME, for: UIControlState.normal)
            labelbutton.sizeToFit()

        if(user["profile_photo_url"] != nil) {
            print(" TROUVÉ PROFILE PHOTO URL NON NIL ET C'EST \(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(" LE CADRE DU BOUTON EST \(button.frame)")

    } else {

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

    }

description de l'image

0 votes

Avez-vous utilisé la vue de pile dans la barre de navigation?

0 votes

@V.Khambir Nop... :/

0 votes

Est-ce que ce rapport de bug est quelque part?

188voto

Vlad Khambir Points 3215

Raison

Le problème apparaît car à partir d'iOS 11, UIBarButtonItem utilise autolayout au lieu de travailler avec des frames.

Solution

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

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

PS

bouton n'est pas un UIBarButtonItem, c'est un UIButton à l'intérieur d'un UIBarButtonItem. Vous devriez définir des contraintes non pas pour UIBarButtonItem, mais pour les éléments à l'intérieur de celui-ci.

3 votes

@V.Khambir maintenant j'ai ce problème. Mais avec cette même solution avec xcode 9, et si je l'exécute sur un appareil ios 1, c'est bien... Mais si je l'exécute sur un appareil ios 10, mes images de bouton de barre ne s'affichent pas du tout. Comment puis-je résoudre ce problème pour toutes les versions ? J'ai vérifié sur des appareils des deux IOS 11, IOS 10. Seulement bien affiché dans la version IOS 1. Dans IOS 10, l'image ne s'affiche pas du tout.

0 votes

@spikesa, cela devrait fonctionner sur les deux versions d'iOS, vous avez probablement défini des contraintes incorrectes.

0 votes

@V.Khambir La valeur de type 'UIBarButtonItem' n'a pas de membre 'widthAnchor' dans Xcode 9 à l'intérieur d'une condition if #available(iOS 11.0, *) ?

53voto

lorenzo gonzalez Points 1184

Merci à tous pour votre contribution! vous avez raison!. pour xcode9 ios11 vous avez besoin de mettre une contrainte.

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

1 votes

Cela a également fonctionné pour moi, mais quelqu'un peut-il expliquer pourquoi c'est nécessaire pour iOS 11 alors que ce ne l'était jamais auparavant ?

9 votes

UINavigationBar dispose maintenant la disposition de ses sous-vues en utilisant Auto Layout

2 votes

Ne commettez pas la même erreur que moi : j'ai désactivé translatesAutoresizingMaskIntoConstraints et j'ai ensuite découvert que cela avait complètement cassé iOS 9 (mais semblait bien fonctionner sur iOS 10 et 11)

18voto

Ahmad Farrag Points 232

Eh bien, le nouveau barButtonItem utilise l'autolayout au lieu de manipuler les 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 correspondre à la taille nécessaire du bouton, avant de l'ajouter au bouton.

18voto

SHS Points 41

Le code Objective C est désormais obsolète. 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) en Objective C peut être utile.

//  UIView+Navbar.h

#import 

@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];

0 votes

Cool. En fait, j'avais aussi besoin de la version Objective-C. Au fait, Xcode 9 redimensionne aléatoirement les éléments de la barre de navigation dans le storyboard. Je dois vérifier à chaque fois avant de pousser mes modifications. J'espère que cela sera bientôt corrigé.

0 votes

Tu es mon héros, car j'ai besoin de refacturer d'anciens projets avec Objective-C.

14voto

Karoly Nyisztor Points 1410

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

// Utilisation
button.applyNavBarConstraints(size: (width: 33, height: 33))

0 votes

Super idée! Appliqué à celui-ci, le UIButton fonctionne très bien.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X