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.
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.
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é).
Cette méthode a très bien fonctionné pour moi .:
Dans Xib sélectionnez le bouton et définissez user defined runtime attributes
:
self.imageView.contentMode
Number
1
Nous utilisons le nombre parce que vous ne pouvez pas utiliser enum ici Mais UIViewContentModeScaleAspectFit est égal à 1.
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];
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.
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];
Voici une réponse alternative à Swift:
myButton.imageView?.contentMode = .ScaleAspectFit
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)
Cela a fonctionné pour moi
[button.imageView setContentMode:UIViewContentModeScaleAspectFit];
Merci à @ayreguitar pour son commentaire
btn.imageView.contentMode = UIViewContentModeScaleAspectFit;
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):
Ensuite, définissez sa classe:
Vous avez terminé!
Au lieu de
l’ajustement de l’image de votre bouton est maintenant comme prévu:
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);
Les modes de contenu UIView s'appliquent au "contenu" correspondant de CALayer. Cela fonctionne pour UIImageView
s 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.
Cela recoupe beaucoup d’autres réponses, mais la solution pour moi était de
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
;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()
}
}
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:
Et voici le fichier Swift:
import UIKit
class TRAspectButton : UIButton {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.imageView?.contentMode = .ScaleAspectFit
}
}
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.
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
[button sizeToFit]
a travaillé pour moi.