web-dev-qa-db-fra.com

UIButton n'ira pas à Aspect Fit dans iPhone

J'ai quelques boutons UIB et, dans IB, ils sont configurés sur Aspect Fit, mais pour une raison quelconque, ils s'étirent toujours. Y a-t-il autre chose que vous devez définir? J'ai essayé tous les différents modes d'affichage et aucun d'entre eux ne fonctionne, ils s'étirent tous.

88
marty

J'ai déjà eu ce problème auparavant. Je l'ai résolu en plaçant mon image dans une UIImageView, où les paramètres contentMode fonctionnent réellement, et en plaçant une UIButton personnalisée transparente au-dessus de cela.

EDIT: Cette réponse est obsolète. Voir Réponse de @Werner Altewischer pour la réponse correcte dans les versions modernes d'iOS.

41
Dan Ray

La solution consiste à définir contentMode sur la propriété imageView de UIButton. La UIButton doit être créée avec un type personnalisé pour que cela fonctionne, je crois (sinon, nil est renvoyé pour cette propriété).

216
Werner Altewischer

Cette méthode a très bien fonctionné pour moi .:

Dans Xib sélectionnez le bouton et définissez user defined runtime attributes:

  • Chemin de la clé: self.imageView.contentMode
  • Type: Number
  • Valeur: 1

Click here to see more clearly the solution

Nous utilisons le nombre parce que vous ne pouvez pas utiliser enum ici Mais UIViewContentModeScaleAspectFit est égal à 1.

44

Si vous le faites dans Interface Builder, vous pouvez utiliser l'inspecteur d'attributs d'exécution pour le définir directement, sans code.

Définissez le chemin de la clé sur le bouton comme étant "imageView.contentMode" avec le type "Nombre" et la valeur "1" (ou le mode de votre choix).

 imageview.contentMode = 1

18
averydev

Utilisez l'imageView du bouton pour contentMode. Pas directement sur le bouton lui-même.

homeButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
homeButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
homeButton.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
[homeButton setImage:[UIImage imageNamed:kPNGLogo] forState:UIControlStateNormal];
10
Ahmed Elashker

Si vous placez l'image dans une UIImageView derrière le bouton, vous perdrez la fonctionnalité intégrée de la classe UIButton, telle que adjustsImageWhenHighlighted et adjustsImageWhenDisabled, et bien sûr la possibilité de définir différentes images pour différents états (sans le de le faire vous-même).

Si nous voulons avoir une image non forcée pour tous les états de contrôle , l’approche consiste à obtenir l’image en utilisant imageWithCGImage:scale:orientation, comme dans la méthode suivante:

- (UIImage *) getScaledImage:(UIImage *)img insideButton:(UIButton *)btn {

    // Check which dimension (width or height) to pay respect to and
    // calculate the scale factor
    CGFloat imgRatio = img.size.width / img.size.height, 
            btnRatio = btn.frame.size.width / btn.frame.size.height,
            scaleFactor = (imgRatio > btnRatio 
                           ? img.size.width / btn.frame.size.width
                           : img.size.height / btn.frame.size.height;

    // Create image using scale factor
    UIImage *scaledImg = [UIImage imageWithCGImage:[img CGImage]
                                             scale:scaleFactor
                                       orientation:UIImageOrientationUp];
    return scaledImg;
}

Pour implémenter ceci, nous écririons:

UIImage *scaledImg = [self getScaledImage:myBtnImg insideButton:myBtn];
[myBtn setImage:scaledImg forState:UIControlStateNormal];

Cela devrait empêcher l’image de s’étirer dans tous les états de contrôle. Cela a fonctionné pour moi, mais laissez-moi savoir si cela ne fonctionne pas!

NOTE: Nous abordons ici un problème relatif à UIButton, mais le insideButton: pourrait aussi bien être insideView:, ou le modèle dans lequel vous voudriez insérer l'image.

6
Alexander Wallin

J'ai eu ce problème il y a quelque temps. Le problème que j’avais était que j’essayais d’appliquer cet effet à l’arrière-plan UIButton, qui est limité et signifie donc que vous ne pouvez pas l’ajuster aussi facilement.

L'astuce consiste à la définir comme une simple image, puis à appliquer la technique de @ayreguitar et cela devrait résoudre le problème!

UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myButton setContentMode:UIViewContentModeScaleAspectFill];
[myButton setImage:@"myImage.png" forState:UIControlStateNormal];
6
Joe Barbour

Voici une réponse alternative à Swift:

myButton.imageView?.contentMode = .ScaleAspectFit
4
João Neves

Combinaison de plusieurs réponses différentes dans une solution - créez un bouton avec un type personnalisé, définissez la propriété imageView contentMode du bouton, puis définissez l'image du bouton (et non l'image d'arrière-plan, qui sera toujours à l'échelle).

//Objective-C:
UIImage *image = [UIImage imageNamed:"myImageName.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:image forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFit;

//Swift:
let image = UIImage(named: "myImageName.png")
let button = UIButton(type: .custom)
button.imageView?.contentMode = .scaleAspectFit
button.setImage(image, for: .normal)
4
Swindler

Cela a fonctionné pour moi 

[button.imageView setContentMode:UIViewContentModeScaleAspectFit];

Merci à @ayreguitar pour son commentaire

4
Karan Alangat
btn.imageView.contentMode = UIViewContentModeScaleAspectFit;
3
selaband

Cette réponse est basée sur @ la réponse de WernerAltewischer .

Pour éviter d'avoir à connecter mon bouton à un IBOutlet afin d'exécuter le code, j'ai sous-classé la classe UIButton:

// .h
@interface UIButtonWithImageAspectFit : UIButton
@end

// .m
@implementation UIButtonWithImageAspectFit

- (void) awakeFromNib {
    [self.imageView setContentMode:UIViewContentModeScaleAspectFit];
}

@end



Créez maintenant un bouton personnalisé dans votre xib et définissez son image (pas l'image d'arrière-plan):

UIButtonWithImageAspectFit: create and set image


Ensuite, définissez sa classe:

UIButtonWithImageAspectFit: set custom class

Vous avez terminé!
Au lieu de
UIButton without image aspect fit
l’ajustement de l’image de votre bouton est maintenant comme prévu:
UIButton with image aspect fit

2
Guillaume

J'ai eu des problèmes avec le redimensionnement proportionnel de l'image, donc la façon dont je l'ai corrigée utilisait des incrustations Edge.

fooButton.contentEdgeInsets = UIEdgeInsetsMake(10, 15, 10, 15);
1
ninjaneer

Les modes de contenu UIView s'appliquent au "contenu" correspondant de CALayer. Cela fonctionne pour UIImageViews car ils fixent le contenu CALayer à la CGImage correspondante.

drawRect: rend finalement le contenu de la couche.

Une UIButton personnalisée (pour autant que je sache) n'a pas de contenu (les boutons de style arrondis-rect peuvent être rendus avec du contenu). Le bouton a des sous-vues: l'arrière-plan UIImageView, l'image UIImageView et le titre UILabel. Définir contentMode sur les sous-vues peut faire ce que vous voulez, mais déconner avec la hiérarchie des vues UIButton est un peu un non-non.

1
tc.

Cela recoupe beaucoup d’autres réponses, mais la solution pour moi était de

  • définissez la contentMode de la UIImageView du bouton sur .ScaleAspectFit - ce qui peut être effectué dans les "Attributs d'exécution définis par l'utilisateur" dans Interface Builder (ie. self.imageView.contentMode, Number, 1) ou dans une sous-classe UIButton;
  • désactiver ”auto-dimensionner les sous-vues”;
  • définissez «Bord» sur «Image» et les valeurs «Haut» et «Bas» appropriées pour «Encadré» (ce qui peut être nécessaire uniquement si, comme moi, vous utilisiez un PDF comme image).
1
plindberg

ios 12. Vous devez également ajouter le contenu Alignement

class FitButton: UIButton {

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)


    }

    override func layoutSubviews() {
        self.imageView?.contentMode = .scaleAspectFill
        self.contentHorizontalAlignment = .fill
        self.contentVerticalAlignment = .fill
        super.layoutSubviews()


    }

}
0
João Nunes

Semblable à @Guillaume, j'ai créé une sous-classe d'UIButton sous forme de fichier Swift. Puis définissez ma classe personnalisée dans Interface Builder:

 interface builder .

Et voici le fichier Swift:

import UIKit

class TRAspectButton : UIButton {
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.imageView?.contentMode = .ScaleAspectFit
    }
}
0
Motine

Vous pouvez utiliser imageWithCGImage comme indiqué ci-dessus (mais sans les parenthèses manquantes).

De plus, des millions de téléphones non-4.0 ne fonctionneront pas du tout avec ce code.

0
Alice

Changer UIButton.imageView.contentMode ne fonctionne pas pour moi.
J'ai résolu le problème en définissant l'image sur la propriété 'Fond'.
Vous pouvez ajouter une contrainte de ratio si vous avez besoin

0
Soohwan Park

[button sizeToFit] a travaillé pour moi.

0
Hila