web-dev-qa-db-fra.com

Comment empêcher l'image d'arrière-plan d'un bouton de s'étirer?

J'attribue un UIButton UIButtonTypeCustom à un UIView avec une image d'arrière-plan plus petite que celle du bouton. La raison pour laquelle l'image est plus petite est parce que j'essaie d'ajouter plus d'une "zone cible" pour le UIButton. Toutefois, l'image est redimensionnée à la taille complète du cadre, plutôt que d'être simplement à la taille de l'image.

J'ai essayé de définir la propriété imageView contentMode de UIButton et UIButton sur "UIViewContentModeScaleAspectFit", mais sans succès, l'image est toujours étendue.

Existe-t-il un moyen de faire ce que j'essaie de faire par programme?

Merci d'avance!

49
Raphael Caixeta

Beaucoup de gens font la même erreur que vous en ce qui concerne les images de boutons, puis sautent dans les cerceaux en essayant de faire en sorte que le bouton se comporte comme ils le souhaitent. Clarifions cela une fois pour toutes: 

Une UIButton peut afficher deux types d’images: une image de premier plan et une image d’arrière-plan . L'image d'arrière-plan d'un bouton doit remplacer la texture d'arrière-plan du bouton. En tant que tel, il est logique que s'étire pour remplir tout l'arrière-plan. Cependant, l'image au premier plan du bouton devrait être une icône pouvant ou non s'afficher à côté du texte; ça ne va pas s'étirer. Il peut se réduire si le cadre est plus petit que l'image, mais cela ne s'étire pas. Vous pouvez même définir l'alignement de l'image au premier plan à l'aide des propriétés d'alignement du contrôle dans Interface Builder.

L'image de premier plan et d'arrière-plan d'un bouton peut être définie dans le code suivant:

// stretchy
[self setBackgroundImage:backgroundImage forState:UIControlStateNormal];  

// not stretchy
[self setImage:forgroundImage forState:UIControlStateNormal]; 
124
memmons

Vous n'avez pas accès à l'imageView d'arrière-plan, mais la solution de contournement fonctionne:

EDIT: Il existe une solution de contournement encore meilleure que celle que j'avais précédemment publiée. Vous pouvez créer un UIImage à partir de n'importe quelle couleur, et appeler -setBackgroundImage:forState.

Voir bradley's answer, here: https://stackoverflow.com/a/20303841/1147286


Réponse originale:

Au lieu d'appeler -setBackgroundImage:forState:, créez un nouveau UIImageView et ajoutez-le en tant que sous-vue du bouton.

UIImageView *bgImageView = [[UIImageView alloc] initWithImage:img];
bgImageView.contentMode = UIViewContentModeScaleAspectFit;
[bgImageView setFrame:CGRectMake(0, 0, videoButton.frame.size.width, videoButton.frame.size.height)];
bgImageView.tag = 99;
[yourButton addSubview:bgImageView];
[yourButton bringSubviewToFront:yourButton.imageView];
  1. Créer l'imageview
  2. Définir le mode de contenu et le cadre
  3. J'ai également défini une balise reconnaissable afin que, lorsque l'écran pivote, je puisse facilement trouver mon imageView personnalisée dans les sous-vues du bouton et réinitialiser son cadre.
  4. Ajoutez-le en tant que sous-vue au bouton
  5. Amenez l'image frontale View du bouton à l'avant pour que notre imageView personnalisée ne le chevauche pas

Lorsque le bouton doit pivoter, il suffit de rechercher l'imageView par son tag et de réinitialiser son cadre:

UIImageView *bgImageView = (UIImageView *)[button viewWithTag:99];
[bgImageView setFrame:CGRectMake(0, 0, newWidth, newHeight)];
8
Zoltán Matók

La manière la plus propre et la plus simple consiste probablement à utiliser les encarts de titre du bouton.

Vous définissez votre image comme image de bouton, puis vous modifiez l'encadré de titre de gauche pour qu'il corresponde moins la largeur de votre image:

myButton.titleEdgeInsets = UIEdgeInsetsMake(0, -myImage.width, 0, 0)

Cela ramènera le texte là où il se trouvait avant l'ajout de l'image à sa gauche. Vous pouvez également utiliser cette valeur pour ajouter du rembourrage à votre bouton.

1
AntonyG

Je suis tombé sur ce problème aussi. 

L'ajout d'image par programme, comme l'a expliqué soigneusement Memmons, n'a pas aidé :( 

J'avais un bouton 100x40 et une image 100x100, cela semblerait pincé, pas ajusté, comme on pourrait le déduire de l'option "Aspect Fit" En fait, aucune de ces options d'affichage n'a eu d'effet.

Je devais simplement le redimensionner pour qu'il tienne sur un bouton, puis utilisez setImage:

UIImage *img=[UIImage imageNamed:@"myimage.png"];
CGImageRef imgRef = [img CGImage];
CGFloat imgW = CGImageGetWidth(imgRef);
CGFloat imgH = CGImageGetHeight(imgRef);
CGFloat btnW = myBttn.frame.size.width;
CGFloat btnH = myBttn.frame.size.height;
//get lesser button dimension
CGFloat minBtn=btnW;
if (btnW>btnH) {
    minBtn=btnH;
}
//calculate scale using greater image dimension
CGFloat scl=imgH/minBtn;
if (imgW>imgH) {
    scl=imgW/minBtn;
}
//scale image
UIImage *scaledImage = [UIImage imageWithCGImage:[img CGImage] scale:(img.scale * scl) orientation:(img.imageOrientation)];
//clean up
UIGraphicsEndImageContext();
//set it on a button
[myBttn setImage:scaledImage forState:UIControlStateNormal];
0
Boris Gafurov

pourrait aider quelqu'un

button.subviews.first?.contentMode = .scaleAspectFit
0
ARSHWIN DENUEV LAL

Une autre considération est la contrainte BaseLine. Si cette contrainte est définie pour vos boutons (représentée par une ligne horizontale ou verticale passant par plusieurs contrôles de votre disposition), les images s’étireront sans étirer le contrôle de bouton sous-jacent. Si votre bouton est par ailleurs correctement contraint (espaces de début, de fin et de bas en haut, etc.), la suppression de la contrainte BaseLine ne devrait pas avoir d'impact sur la mise en page, tout en permettant à l'image de premier plan de s'adapter correctement à la forme du bouton sous-jacent.

0
Epsilon3

Je suppose que la solution la plus simple consiste à utiliser la méthode resizableImageWithCapInsets de UIImage. Utilisez UIEdgeInsetsMake pour configurer les espaces libres.

0
MacMark