¿UIButton no escucha la configuración del modo de contenido?

91

firstButton es un UIButton de tipo Custom. Estoy poniendo programáticamente tres de ellos en cada celda de una tabla, así:

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

En otra parte, se lo digo a clipToBounds. Lo que obtengo es un recorte del cuadrado central de la imagen, en lugar de una representación en escala de aspecto. He intentado esto de muchas maneras, incluida la configuración de la propiedad de modo en firstButton.imageView, que tampoco parece funcionar.

Dan Ray
fuente
1
Vea la solución de Chris Nolet a continuación: button.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;
Matt
Consulte stackoverflow.com/a/28205566/481207, que muestra que la configuración de contentVerticalAlignment y contentHorizontalAlignment es necesaria para UIViewContentModeScaleAspectFit.
Matt

Respuestas:

187

Yo tuve el mismo problema. Veo que esta pregunta es un poco antigua, pero quiero proporcionar una respuesta clara y correcta para que otras personas (como yo) no tengan tiempo cuando aparezca en sus resultados de búsqueda.

Me tomó un poco de búsqueda y experimentación, pero encontré la solución. Simplemente configure el ContentMode del ImageView "oculto" que está dentro del UIButton.

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

Quizás a eso se refería Dan Ray en su respuesta aceptada, pero sospecho que no.

Dave
fuente
1
No, no lo fue. La solución que me decidí fue usar un UIImageView para mantener la imagen, luego un UIButton claro y transparente de tipo "personalizado" encima.
Dan Ray
Dave, en iOS 3.2 al menos, tu solución no parece funcionar para mí. Lástima, porque esperaba obtener el resaltado de la imagen al hacer clic "gratis". Incluso me aseguré de que button.imageView no fuera nulo donde estaba configurando contentMode, y configuré la imagen después de configurar contentMode, tal como lo estás haciendo.
Jacques
2
Solo para aclarar, "no funciona" significa que "la imagen se muestra en su resolución completa, no reducida como esperaba".
Jacques
Jacques, lo anterior me funciona en iOS 4.x. Desafortunadamente, puedo reproducir el problema de "no cambiar de tamaño" cuando construyo con un objetivo v3.2. Intenté cambiar el tamaño del marco de la vista UIButton, pero eso tampoco pareció ayudar. ugh.
Dave
4
Vea la solución de Chris Nolet a continuación: button.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;
Matt
74

Si está tratando con la imagen de UIButton (a diferencia de su backgroundImage), configurar contentMode en el UIButton en sí o en su imageView no tiene ningún efecto (a pesar de lo que digan otras respuestas).

Alternativamente, haz esto en su lugar:

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

O dimensione su imagen en consecuencia.

O simplemente use un UIImageView (que respete adecuadamente el contentMode) con un UITapGestureRecognizer adjunto, o un UIButton transparente encima.

Alfie Hanssen
fuente
4
Esto funciona para mi caso en iOS 7, mientras que todos los demás aquí no.
Byte
5
Configurar contentHorizontalAlignment y contentVerticalAlignment es la solución correcta. Consulte stackoverflow.com/a/28205566/481207 para obtener una explicación.
Matt
1
Esta es la respuesta que estaba buscando.
ninjaneer
4
Esta respuesta es incorrecta. Usted no necesita conjunto contentModeen el imageViewque si quieres hacer cualquier tipo de relleno aspecto o forma, como otras respuestas han aclarado. Consulte: stackoverflow.com/a/7944316/746890 .
Chris Nolet
51

En lugar de configurar el contentModebotón en sí, querrá configurar contentHorizontalAlignmenty contentVerticalAlignmentpropiedades y (fundamentalmente) las contentModedel botón imageViewpara cualquier tipo de relleno o ajuste de aspecto. He aquí un ejemplo:

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

Por supuesto, también puede hacer otras cosas como alinear la imagen del botón con la parte superior del botón. Si no necesita un relleno o ajuste de aspecto, puede establecer la alineación por sí mismo:

button.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;

En Swift, querrá usar:

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

Esto funciona para todas las versiones de iOS, incluidas las últimas versiones con diseño automático (es decir, iOS 4 hasta iOS 11+).

Chris Nolet
fuente
2
Gracias Chris, eso resolvió mi problema, o mejor dicho, lo hizo en combinación con contentEdgeInsets, para hacer retroceder mi imagen del borde superior solo un poco.
Rob Reuss
7

Después de un par de horas de confusión, así es como hice que funcionara con iOS 3.2. Como mencionó Dusker, usar setBackgroundImage en lugar de setImage hizo el trabajo por mí.

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
fuente
6

La respuesta es usar un UIImageView con todos los encantadores ajustes de modo de contenido que desee y luego colocar un botón personalizado encima. Es tonto que no puedas hacer todo eso de una sola vez, pero parece que no puedes.

Dan Ray
fuente
4

Encontré una solución para esto. Establezca la adjustsImageWhenHighlightedpropiedad de UIButtona NO.

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

Espero que esto ayude. No dude en comentar a continuación, haré un seguimiento de cualquier pregunta que tenga.

iOSDevSF
fuente
Esta es la solución perfecta.
Gaurav
No funciona. Esto simplemente evita que el botón se resalte.
Matt
4

Mi respuesta es similar a la de Kuba. Necesitaba que mi imagen estuviera configurada programáticamente.

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
fuente
3

La única solución que funcionó para mí:

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

Swift 3

self.firstButton.imageView?.contentMode = .scaleAspectFill
Vaibhav Saran
fuente
1

En lugar de setImage, intente setBackgroundImage

dusker
fuente
3
Hmp. A, eso es tonto, debería respetar la configuración del MODO DE CONTENIDO para su CONTENIDO, ¿verdad? Y B, TODAVÍA no parece respetar la configuración del modo - ahora está bloqueado para "estirar" (que es, en este caso, más como "apretar"), y no escala el contenido con respecto a su aspecto proporción.
Dan Ray
1

Creo que tenemos un problema de construcción de interfaz simple aquí: aparentemente, el IB ignora cualquier cambio en el modo de contenido DESPUÉS de que haya establecido la propiedad de la imagen.

la solución es tan simple: configure el modo de contenido, elimine los nombres de imagen establecidos previamente (asegúrese de eliminarlos en todos los estados, predeterminados, resaltados, etc.), luego vuelva a ingresar los nombres de imágenes deseados en todos los estados deseados - et voilà .

John Payne
fuente
1
lo mismo ocurre con la configuración del modo de contenido mediante programación: no configure la imagen ANTES de configurar el modo de contenido
JohnPayne
0

También recomiendo echar un vistazo a la adjustsImageWhenHighlighted UIButtonpropiedad para evitar deformaciones extrañas de la imagen, cuando se presiona el botón.

MonsieurDart
fuente
0

Al tratar de resolver esto, mi método se volvió un poco más complicado a medida que pasaba el tiempo, y terminé subclasificando UIButton y anulando setHighlights:

Para mí, funciona simplemente reducir la imagen alfa a .5, porque están sobre un fondo negro.

Sin embargo, solo funciona si comento [super setHighlights:] (donde parece que el código elástico de la imagen está sucediendo), que simplemente no parece la forma correcta de resolver esto en absoluto ... todo parece estar bien funcionando bien, sin embargo. Veremos cómo se mantiene mientras sigo trabajando en ello.

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

//    [super setHighlighted:highlight];
}
Jankins
fuente
1
En la remota posibilidad de que alguien encuentre esto relevante, mi método anterior pareció funcionar bien hasta que puse los botones en un UIScrollView, donde a veces el resaltado del botón se "atasca", que es lo que sospechaba que eventualmente podría suceder.
Jankins
0

Si alguien busca una respuesta que funcione en iOS 6 e iOS 7 y el guión gráfico:

Puede configurar la imagen en su guión gráfico:

ingrese la descripción de la imagen aquí

Y entonces:

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

Si el UIButton no parece escuchar la configuración de restricción de diseño, verifique si las imágenes son más grandes que el tamaño del botón. Utilice siempre las imágenes @ 2x y @ 3x para resoluciones de retina.

Totoro
fuente
0

Estas dos cosas (que son bastante difíciles de encontrar inicialmente) estirarán la imagen de UIButton para que se ajuste al tamaño del botón:

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

siempre se debe intentar configurarlo en el Storyboard en lugar de en el código.

delta2flat
fuente