UIButton n'écoute pas le paramètre du mode contenu?

91

firstButton est un UIButton de type Custom. J'en mets trois par programmation dans chaque cellule d'un tableau, ainsi:

[firstButton setImage:markImage forState:UIControlStateNormal];
[firstButton setContentMode:UIViewContentModeScaleAspectFit];
[cell.contentView addSubview:firstButton];

Ailleurs, je lui dis de clipToBounds. Ce que j'obtiens, c'est un recadrage du carré central de l'image, plutôt qu'un rendu à l'échelle de son aspect. J'ai essayé de nombreuses façons, notamment en définissant la propriété mode sur firstButton.imageView, qui ne semble pas non plus fonctionner.

Dan Ray
la source
1
Voir la solution de Chris Nolet ci-dessous: button.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;
Matt
Consultez stackoverflow.com/a/28205566/481207 qui montre que la définition à la fois de contentVerticalAlignment et contentHorizontalAlignment est requise pour UIViewContentModeScaleAspectFit.
Matt

Réponses:

187

J'ai eu le même problème. Je vois que cette question est un peu ancienne, mais je veux fournir une réponse claire et correcte pour sauver d'autres personnes (comme moi) un certain temps lorsqu'elle apparaîtra dans leurs résultats de recherche.

Cela m'a pris un peu de recherche et d'expérimentation, mais j'ai trouvé la solution. Définissez simplement le ContentMode de l'ImageView "caché" qui se trouve à l'intérieur de l'UIButton.

[[firstButton imageView] setContentMode: UIViewContentModeScaleAspectFit];
[firstButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];

C'est peut-être à cela que Dan Ray faisait allusion dans sa réponse acceptée, mais je suppose que non.

Dave
la source
1
Non, ce n'était pas le cas. La solution sur laquelle j'ai opté était d'utiliser un UIImageView pour contenir l'image, puis un UIButton clair et transparent de type «personnalisé» par-dessus.
Dan Ray
Dave, sur iOS 3.2 au moins, votre solution ne semble pas fonctionner pour moi. Dommage, car j'espérais obtenir la mise en valeur de l'image en cliquant "gratuitement". Je me suis même assuré que button.imageView n'était pas nul là où je définissais contentMode, et j'ai défini l'image après avoir défini contentMode, comme vous le faites.
Jacques
2
Juste pour clarifier, "ne fonctionne pas" signifie "l'image est affichée à sa pleine résolution, pas réduite comme je l'espérais".
Jacques
Jacques, ce qui précède fonctionne pour moi dans iOS 4.x. Malheureusement, je peux reproduire le problème "ne sera pas redimensionné" lors de la construction avec une cible v3.2. J'ai essayé de changer la taille de l'image de la vue UIButton, mais cela n'a pas semblé aider non plus. Pouah.
Dave du
4
Voir la solution de Chris Nolet ci-dessous: button.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;
Matt
74

Si vous avez affaire à l'image de l'UIButton (par opposition à son backgroundImage), définir le contentMode sur l'UIButton lui-même ou sur son imageView n'a aucun effet (malgré ce que disent les autres réponses).

Sinon, faites ceci à la place:

self.button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
self.button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;

Ou dimensionner votre image en conséquence.

OU utilisez simplement un UIImageView (qui respecte correctement contentMode) avec un UITapGestureRecognizer attaché, ou un UIButton transparent au-dessus.

Alfie Hanssen
la source
4
Cela fonctionne pour mon cas dans iOS 7 alors que tous les autres ici ne le font pas.
Octet du
5
La définition de contentHorizontalAlignment et contentVerticalAlignment est la bonne solution. Voir stackoverflow.com/a/28205566/481207 pour une explication.
Matt
1
C'est la réponse que je cherchais.
ninjaneer
4
Cette réponse est incorrecte. Vous avez besoin de mettre contentModesur le imageViewsi vous voulez faire une sorte d'aspect remplissage ou en forme, que d' autres réponses ont permis de clarifier. Consultez: stackoverflow.com/a/7944316/746890 .
Chris Nolet
51

Plutôt que de fixer le contentModesur le bouton lui - même, vous voulez définir contentHorizontalAlignmentet contentVerticalAlignmentpropriétés et (cruciale) le contentModepour le bouton de imageViewpour tout type d'aspect remplissage ou en forme. Voici un exemple:

button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
button.imageView.contentMode = UIViewContentModeScaleAspectFit;

Bien sûr, vous pouvez également faire d'autres choses comme aligner l'image du bouton en haut du bouton. Si vous n'avez pas besoin d'un remplissage ou d'un ajustement d'aspect, vous pouvez simplement définir l'alignement par lui-même:

button.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;

Dans Swift, vous voudrez utiliser:

button.contentHorizontalAlignment = .fill
button.contentVerticalAlignment = .fill
button.imageView?.contentMode = .scaleAspectFit

Cela fonctionne pour toutes les versions d'iOS, y compris les dernières versions avec mise en page automatique (c'est-à-dire iOS 4 jusqu'à iOS 11+).

Chris Nolet
la source
2
Merci Chris - cela a résolu mon problème, ou plutôt, il l'a fait en combinaison avec contentEdgeInsets, afin de reculer un peu mon image du bord supérieur.
Rob Reuss
7

Après quelques heures de confusion, voici comment je l'ai fait fonctionner sous iOS 3.2. Comme Dusker l'a mentionné, utiliser setBackgroundImage au lieu de setImage a fait le travail pour moi.

CGRect myButtonFrame = CGRectMake(0, 0, 250, 250);
UIImage *myButtonImage = [UIImage imageNamed:@"buttonImage"];

UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];

[myButton setBackgroundImage:myButtonImage forState:UIControlStateNormal];
[myButton setFrame: myButtonFrame];
[myButton setContentMode: UIViewContentModeScaleAspectFit];
Pierre
la source
6

La réponse est d'utiliser une UIImageView avec tous les jolis paramètres du mode de contenu que vous souhaitez, puis de superposer un bouton personnalisé au-dessus. C'est stupide que vous ne pouvez pas faire tout cela d'un seul coup, mais il semble que vous ne puissiez pas.

Dan Ray
la source
4

J'ai trouvé un correctif pour cela. Définissez la adjustsImageWhenHighlightedpropriété de UIButtonsur NO.

  UIButton *b = [[UIButton alloc] initWithFrame:rect];
        [b setImage:image forState:UIControlStateNormal];
        [b.imageView setContentMode:UIViewContentModeScaleAspectFill];
        [b setAdjustsImageWhenHighlighted:NO];

J'espère que cela t'aides. N'hésitez pas à commenter ci-dessous, je ferai le suivi de toutes vos questions.

iOSDevSF
la source
C'est la solution parfaite.
Gaurav
Ça ne marche pas. Cela empêche simplement le bouton de se mettre en surbrillance.
Matt
4

Ma réponse est similaire à celle de Kuba. J'avais besoin que mon image soit définie par programme.

UIImage *image = [[UIImage alloc] initWithContentsOfFile:...];
[button setBackgroundImage:image forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFill; //this is needed for some reason, won't work without it.
for(UIView *view in button.subviews) {
    view.contentMode = UIViewContentModeScaleAspectFill;
}
ninjaneer
la source
3

Seule solution qui a fonctionné pour moi:

[button setImage:image forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFill;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
Tariq
la source
3

Swift 3

self.firstButton.imageView?.contentMode = .scaleAspectFill
Vaibhav Saran
la source
1

Au lieu de setImage, essayez setBackgroundImage

crépuscule
la source
3
Hmp. R, c'est idiot, il devrait respecter le paramètre CONTENT MODE pour son CONTENT, non? Et B, il semble TOUJOURS ne pas respecter le réglage du mode - il est maintenant verrouillé sur "stretch" (qui est, dans ce cas, plus comme "squeeze"), et ne redimensionne pas le contenu par rapport à son aspect rapport.
Dan Ray
1

Je crois que nous avons ici un problème de création d'interface simple - apparemment, l'IB ignore tout changement de mode de contenu APRÈS que vous ayez défini la propriété image.

la solution est aussi simple: définissez le mode de contenu, supprimez les noms d'image précédemment définis (assurez-vous de le supprimer dans tous les états, par défaut, en surbrillance, etc.), puis entrez à nouveau les noms d'image souhaités dans tous les états souhaités - et voilà .

JohnPayne
la source
1
il en va de même pour définir le mode de contenu par programmation - ne pas définir l'image AVANT de définir le mode de contenu
JohnPayne
0

Je conseille également de jeter un œil à la adjustsImageWhenHighlighted UIButtonpropriété pour éviter d'étranges déformations de l'image, lorsque le bouton est enfoncé.

MonsieurDart
la source
0

En essayant de comprendre cela, ma méthode est devenue un peu plus pirate avec le temps, et j'ai fini par sous-classer UIButton et surcharger setHighlighted:

Pour moi, cela fonctionne pour simplement abattre l'image alpha à 0,5, car elles sont sur un fond noir.

Cependant, cela ne fonctionne que si je commente [super setHighlighted:] (où il apparaît que le code extensible de l'image est en cours), ce qui ne semble tout simplement pas être la bonne façon de résoudre ce problème ... tout semble être fonctionne bien, cependant. Nous verrons comment cela résiste au fur et à mesure que je continue à travailler dessus.

- (void)setHighlighted:(BOOL)highlight {
    if (highlight) {
        [self.imageView setAlpha:.5];
    }  else {
        [self.imageView setAlpha:1];        
    }

//    [super setHighlighted:highlight];
}
jankins
la source
1
Au cas où quelqu'un trouverait cela pertinent, ma méthode ci-dessus semblait fonctionner correctement jusqu'à ce que je mette les boutons sur un UIScrollView, où parfois le surlignage du bouton est resté "bloqué", ce que je soupçonnais pourrait éventuellement se produire.
jankins
0

Si quelqu'un cherche une réponse qui fonctionne dans iOS 6 et iOS 7 et storyboard:

Vous pouvez définir l'image dans votre storyboard:

entrez la description de l'image ici

Puis:

for(UIView* testId in self.subviews) {
    if([testId isKindOfClass:[UIImageView class]])
        [testId setContentMode:UIViewContentModeScaleAspectFill];
}
Jakub
la source
0

Si l'UIButton ne semble pas écouter les paramètres de contrainte de disposition, vérifiez si les images sont plus grandes que la taille du bouton. Utilisez toujours les images @ 2x et @ 3x pour les résolutions de la rétine.

Totoro
la source
0

Ces deux choses (qui sont assez difficiles à trouver au départ) étireront votre image UIButton pour l'adapter à la taille du bouton:

entrez la description de l'image ici entrez la description de l'image ici

on devrait toujours essayer de définir un tel dans le Storyboard plutôt que dans le code.

delta2flat
la source