2011-12-30 10 views
47

Estoy asignando un UIButtonTypeCustom UIButton a una UIView con una imagen de fondo que es más pequeña que el marco del botón. La razón por la cual la imagen es más pequeña es porque estoy tratando de agregar más de un "área objetivo" para el UIButton. Sin embargo, la imagen se está escalando al tamaño completo del marco, en lugar de solo ser el tamaño de la imagen.¿Cómo evito que se estire la imagen de fondo de un botón?

He intentado configurar UIButton y la propiedad imageView contentMode de UIButton en "UIViewContentModeScaleAspectFit", pero no hay suerte, la imagen aún se alarga.

¿Hay alguna manera de hacer lo que estoy tratando de hacer programáticamente?

¡Gracias de antemano!

+4

¿De verdad necesita que sea la imagen de fondo ? ¿Necesitas escribir texto o colocar otra imagen sobre él? De lo contrario, utilice la imagen y no la imagen de fondo, ya que solo la imagen de fondo se estira de forma predeterminada para que coincida con el marco. –

+0

@Raphael ¿Ninguna de estas respuestas es adecuada? – memmons

Respuesta

-2

Lo que necesita hacer es agregar su imagen como UIImageView.

Después de agregar un botón con fondo transperent (UIColor ClearColor) encima de él con su ancho y alto deseados.

+0

Eso es en realidad una mala sugerencia, ya que la imagen no formará parte del botón y no reflejará los cambios de estado (lo que frustraría el propósito de tener una imagen como parte del botón). – GtotheB

+0

Para que pueda cambiar la imagen cuando se toca el botón para imitar el cambio de estado – ozba

+0

@ozba Los cambios de estado para las imágenes ya son compatibles con el botón. Agregar una imagen de fondo detrás de un botón claro para imitar un botón con una imagen casi nunca es una buena idea y generalmente una muy mala. – memmons

120

Mucha gente comete el mismo error que usted en lo que respecta a las imágenes de los botones y luego salta por los aros tratando de hacer que el botón se comporte como lo esperaban. Vamos a aclarar esto de una vez por todas:

A UIButton tiene dos tipos de imágenes que puede mostrar: una imagen de primer plano y una imagen de fondo. Se espera que la imagen de fondo de un botón reemplace la textura de fondo del botón. Como tal, tiene sentido que se extienda para llenar el fondo completo. Sin embargo, se espera que la imagen de primer plano del botón sea un ícono que puede o no mostrarse junto con el texto; no se estirará Es puede encoger si el marco es más pequeño que la imagen, pero no se estirará. Incluso puede establecer la alineación de la imagen de primer plano utilizando las propiedades de alineación de control en el Generador de interfaces.

imagen en primer plano y el fondo de un botón se puede configurar en código como este:

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

// not stretchy 
[self setImage:forgroundImage forState:UIControlStateNormal]; 
+49

¿Qué hace cuando necesita una imagen que no se estira para mostrarse con texto en la parte superior? –

+0

Extraño, cada vez que configuro la propiedad de imagen UIButton, el texto del título desaparece. Hay alguna manera de prevenir eso? editar: Oh, el texto está a la derecha ... raro, supongo que jugaré con los ajustes hasta que esté directamente debajo de la imagen de primer plano – powerj1984

+0

@ powerj1984 Si desea que el texto se coloque encima de una imagen, debe usando una imagen de fondo. Se espera que la imagen de primer plano sustituya el texto o se siente al lado del texto. Si está ajustando su texto para forzarlo a colocarse sobre la imagen de primer plano, lo está haciendo mal. – memmons

0

Otra consideración es la restricción de referencia. Si sus botones tienen este conjunto de restricciones (representado como una línea horizontal o vertical a través de múltiples controles en su diseño), causará que sus imágenes se estiren sin estirar el control del botón subyacente. Si su botón está restringido adecuadamente (espacios inicial/final y superior/inferior, etc.) la eliminación de la restricción BaseLine no debería tener ningún impacto en el diseño, al tiempo que permite que la imagen de primer plano se adapte correctamente a la forma del botón subyacente.

-1

Answerbot responde a la pregunta con lo que es correcto y correcto hacer. No pelear contra el sistema operativo y usar las cosas como se espera siempre es un buen consejo. Sin embargo, a veces es necesario romper las reglas.

Pude enmascarar la imagen de fondo ampliada (no evitarla) superponiéndola con un CAlayer negro y luego superponiéndola con una imagen de tamaño correcto CAlayer. Todo esto se hizo creando una subclase de UIButton y sobrescribiendo el método setHighlighted.

¿Necesita este código?

- (void)setHighlighted:(BOOL)highlighted 
{ 
super.highlighted = highlighted; 

// 
//Whenever an image needs to be highlighted, create a dimmed new image that is correctly  sized. Below it is a englarged stretched image. 
// 
if (highlighted != _previousHighlightedSate) 
{ 
    _previousHighlightedSate = highlighted; 

    if (highlighted) 
    { 
     //Create a black layer so image can dim 
     _blackLayer = [CALayer layer]; 
     _blackLayer.bounds = self.bounds; 
     CGRect rect = _blackLayer.bounds; 
     rect.size.width = rect.size.width*2; 
     rect.size.height = rect.size.height*2; 
     _blackLayer.bounds = rect; 
     _blackLayer.backgroundColor = [[UIColor blackColor] CGColor]; 

     //create image layer 
     _nonStretchImageLayer = [CALayer layer]; 
     _nonStretchImageLayer.backgroundColor = [UIColor blackColor].CGColor; 
     _nonStretchImageLayer.bounds = CGRectMake(0 , 0, self.bounds.size.width, self.bounds.size.height); 
     _nonStretchImageLayer.frame = CGRectMake(0 , 0, self.bounds.size.width, self.bounds.size.height); 
     _nonStretchImageLayer.contentsGravity = kCAGravityResizeAspect;//default is to resize 
     _nonStretchImageLayer.contents = (id)self.imageView.image.CGImage; 
     _nonStretchImageLayer.opacity = 0.5; 

     //add layers to image view 
     [self.imageView.layer addSublayer:_blackLayer]; 
     [self.imageView.layer addSublayer:_nonStretchImageLayer]; 
    } 
    else 
    { 
     //remove from image view 
     [_blackLayer removeFromSuperlayer]; 
     [_nonStretchImageLayer removeFromSuperlayer]; 

     //nil them out. 
     _blackLayer = nil; 
     _nonStretchImageLayer = nil; 
    } 
} 

inspiración para este trabajo alrededor de vino de here

0

supongo que la solución más fácil es utilizar el método de resizableImageWithCapInsets UIImage. Use UIEdgeInsetsMake para configurar los espacios libres.

1

La manera más limpia y más fácil es probablemente usar las inserciones del título del botón.

Usted fija su imagen la imagen del botón como, y luego cambia la inserción título de la izquierda para que coincida menos la anchura de la imagen:

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

Esto moverá el texto de nuevo donde estaba antes de la era agregado a su izquierda. También puede usar este valor para agregar algo de relleno a su botón.

6

Usted no tiene acceso a la imageView fondo, pero no es totalmente solución de trabajo:

EDITAR: Hay una mejor solución entonces lo que he publicado originalmente. Se puede crear un UIImage de cualquier color, y llame -setBackgroundImage:forState.

Ver bradley's respuesta, aquí: https://stackoverflow.com/a/20303841/1147286


Respuesta original:

En lugar de llamar -setBackgroundImage:forState:, cree un nuevo UIImageView y agréguelo como una subvista del botón.

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. crear el imageview
  2. Ajuste el modo de contenido y el marco
  3. También creó una etiqueta reconocible, de modo que cuando la pantalla gira que puedo encontrar fácilmente mi imageView costumbre en subvistas del botón y restablecer su marco
  4. añadirla como una subvista al botón
  5. Llevar el imageView frontal del botón en la parte delantera por lo que nuestro imageView costumbre que no se superponga

Cuando el botón tiene que girar simplemente encontrar el imageView por su etiqueta y restablecer su marco:

UIImageView *bgImageView = (UIImageView *)[button viewWithTag:99]; 
[bgImageView setFrame:CGRectMake(0, 0, newWidth, newHeight)]; 
0

encontré con este problema también.

Adición de imagen mediante programación, como memmons explican a fondo, no ayuda :(

que tenía un botón de 100x40 y 100x100 imagen, parece ser exprimido, sin dispositivos, como cabría inferir de "Aspecto Fit" opción. En realidad, ninguna de esas opciones de visualización tuvo un efecto.

sólo tenía que cambiar la escala que lo que cabría en un botón, a continuación, utilizar 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]; 
-1

Es simple como:

ImageBn.imageView?.contentMode = .scaleAspectFit 
    ImageBn.setImage(chosenImage, for: .normal) 
Cuestiones relacionadas