2010-12-21 13 views
12

Tengo un UIButton en mi aplicación de iPhone. Configuré su tamaño a 100x100.Una manera simple de poner un UIImage en un UIButton

Tengo una imagen que es 400x200 que deseo mostrar en el botón.

El botón STILL necesita permanecer en 100x100 ... y quiero que la imagen se reduzca para ajustarse ... pero mantiene la relación de aspecto correcta.

Pensé que para eso se usaba "Aspect Fit".

¿Incluyo mi imagen con setImage o setBackgroundImage?

¿Debo configurar AspectFit para el botón? o la imagen? o la imagen de fondo?

(necesito las imágenes más pequeñas para aumentar de tamaño. Mientras que las imágenes más grandes deben descrease de tamaño. manteniendo siempre el botón en 100x100.)

He intentado innumerables combinaciones de todo lo anterior ... y me parece que no puede conseguir todo para trabajar al mismo tiempo:

  • no cambiar el tamaño del botón de 100x100.
  • No destruya la relación de aspecto de la imagen.
  • Aumente siempre las imágenes pequeñas para que quepan en el botón.
  • Reduzca siempre las imágenes grandes para que quepan en el botón.
  • Nunca recorte ninguno de los bordes de la imagen.
  • Nunca requiera el truco de "poner UIButtons sobre todos sus UIimages".
  • No es necesario que todos realicen la actualización a v4.2.1 solo para utilizar nuevos métodos de infraestructura.

Veo tantas aplicaciones, con tantos botones de imagen en pleno funcionamiento ... que no puedo creer que no pueda entender esto muy simple, muy común.

Ugh.

Respuesta

1

Coloque una vista de imagen sobre el botón, configure su imagen para la vista de imagen y no para el botón.

Todo lo mejor.

+0

En realidad, me pongo el 'UIImageView' ** ** bajo el botón y hacer que el botón "Custom" por lo que es invisible. –

+2

Quería hacer esto "correctamente" y evitar el hack de 25 botones ... más de 25 imágenes ... tener que crear 50 objetos y toda la memoria, mantenimiento, puntos de venta, acciones, etc. ¿De qué sirven todos los poderosos, métodos de botones incorporados ... si la solución de todos es "simplemente no los uses" ??? – Alice

1

Me gustaría cambiar el tamaño de la imagen a 100x100 manteniendo la relación de aspecto del contenido que figura en la imagen. A continuación, establezca la propiedad backgroundImage del UIButton en la imagen.

+1

Eso es exactamente lo que tengo que hacer ... ¿pero * CÓMO *? (¿No te encanta cuando la "respuesta" de alguien es "solo hazlo" ... en lugar de * CÓMO * hacerlo?) ¿CÓMO cambio el tamaño de la imagen? ¿CÓMO mantengo la relación de aspecto? (Tenga en cuenta que NO quiero cambiar el tamaño de la imagen a 100x100 ... Quiero tener * FIT * dentro de 100x100 (independientemente de su tamaño original, o tamaño nuevo) ... siempre que su ancho (o altura)) se convierte exactamente en 100. – Alice

+0

Hay muchas formas de cambiar el tamaño de una imagen, como http://stackoverflow.com/questions/2658738/the-simplest-way-to-resize-an-uiimage ¿Ha intentado simplemente crear un UIImageView como una subvista del botón? No estoy seguro de si funcionará, pero parece que será la forma más fácil de hacerlo si funciona. –

+0

No nos puede el material legal e indocumentado.Y no puedo obligar a todos a actualizar las estructuras de v4.2.1. – Alice

2

Creo que lo que Dan está tratando de decir (pero sin nunca diciendo que) es hacer esto:

  • Utilice una "imagen temp" para hacer el cambio de tamaño para usted.
  • La imagen temporal debe establecerse en ASPECTO FIT y HIDDEN.
  • Asegúrate de que el botón esté configurado con el tamaño que deseas y NO configúralo en ASPECT FIT.
 
// Make a frame the same size as your button 
CGRect aFrame = CGRectMake(0, 0, myButton.frame.size.width, myButton.frame.size.height); 

// Set your temp-image to the size of your button 
imgTemp.frame = aFrame; 

// Put your image into the temp-image 
imgTemp.image = anImage; 

// Copy that resized temp-image to your button 
[myButton setBackgroundImage:tempImage forState:UIControlStateNormal]; 
+0

Acabo de intentar eso. La imagen temporal sale * PERFECTO *. Pero no hay forma de copiar esa imagen (y su nuevo tamaño) en mi botón. Si uso setBackgroundImage, la imagen se estira y la relación de aspecto se destruye. – Alice

+0

> Asegúrate de que tu botón NO esté ajustado a ASPECT FIT ..................................... Cómo ???? No puedes configurarlo para "nada". Pensé que la opción "sin estiramiento" era "CENTRAL", pero eso se extiende de todos modos. Ugh. – Alice

12

UIButton está roto. Esa es la respuesta corta.El UIImageView s en su imagen y sus propiedades backgroundImage no respetan las configuraciones UIViewContentMode. Son propiedades de solo lectura, y aunque el contenido UIImage de esos UIImageViews se puede establecer a través de los métodos setImage: y setBackgroundImage:, el modo de contenido no puede ser.

La solución es proporcionar imágenes del tamaño adecuado en su paquete para comenzar, o poner un UIImageView abajo, configurarlo de la manera que desee, y luego colocar un UIButton claro sobre la parte superior. Ese es el truco que han usado todas esas aplicaciones profesionales de lujo que has visto, lo prometo. Todos tenemos que hacerlo.

+0

Las imágenes no están en mi paquete ... son imágenes de personas que se cargarán más tarde. Entonces, ¿todas las características de los botones existentes no permiten esta simple cosa? La imagen de un botón es inútil. La imagen de fondo de un botón es inútil. Todas las diversas opciones de ajuste de aspecto son inútiles. (¿Por qué Apple los puso en ... si ni siquiera pueden hacer algo tan simple es "hacer que esta imagen se ajuste a este botón"?) – Alice

+2

Lo sé. Lo sé. –

+0

¿Alguien sabe si esta "molestia" se ha abordado en una versión posterior de xcode? – Jimmy

4

Para hacer esto correctamente, cambiaría el tamaño y manipularía la imagen de forma programática para obtener la relación de aspecto deseada. Esto evita la necesidad de cualquier pirateo de jerarquía de vistas, y también reduce el rendimiento alcanzado en una sola operación, en lugar de cada redibujado.

Este (no probado) código debería ayudar a ilustrar lo que quiero decir:

CGSize imageSize = image.size; 
CGFloat currentAspect = imageSize.width/imageSize.height; 

// for purposes of illustration 
CGFloat targetWidth = 100; 
CGFloat targetHeight = 100; 
CGFloat targetAspect = targetWidth/targetHeight; 

CGFloat newWidth, newHeight; 

if (currentAspect > targetAspect) { 
    // width will end up at 100, height needs to be smaller 
    newWidth = targetWidth; 
    newHeight = targetWidth/currentAspect; 
} else { 
    // height will end up at 100, width needs to be smaller 
    newHeight = targetHeight; 
    newWidth = targetHeight * currentAspect; 
} 

size_t bytesPerPixel = 4; 

// although the image will be resized to { newWidth, newHeight }, it needs 
// to be padded with empty space to provide the aspect fit behavior 
// 
// use calloc() to clear the data as it's allocated 
void *imageData = calloc(targetWidth * targetHeight, bytesPerPixel); 

if (!imageData) { 
    // error out 
    return; 
} 

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
if (!colorSpace) { 
    // error out 
    return; 
} 

CGContextRef context = CGBitmapContextCreate(
    imageData, 
    targetWidth, 
    targetHeight, 
    8, // bits per component 
    targetWidth * bytesPerPixel, // bytes per row 
    colorSpace, 
    kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst 
); 

CGColorSpaceRelease(colorSpace); 

// now we have a context to draw the original image into 
// in doing so, we want to center it, so prepare the geometry 
CGRect drawRect = CGRectMake(
    floor((targetWidth - newWidth)/2), 
    floor((targetHeight - newHeight)/2), 
    round(newWidth), 
    round(newHeight) 
); 

CGContextDrawImage(context, drawRect, image.CGImage); 

// now that the bitmap context contains the aspect fit image with transparency 
// letterboxing, we want to pull out a new image from it 
CGImageRef newImage = CGBitmapContextCreateImage(context); 

// destroy the temporary context 
CGContextRelease(context); 
free(imageData); 

// and, finally, create a new UIImage 
UIImage *newUIImage = [UIImage imageWithCGImage:newImage]; 
CGImageRelease(newImage); 

Avísame si alguna parte de que no está claro.

+0

Wow. Voy a intentar eso también. Pero esta cosa simple es en realidad * ESO * gran desorden de código? Haga que esta imagen encaje dentro de este botón. Realmente, nunca se puede hacer con cosas como "establecer tamaño de botón" y "ajustar aspecto de aspecto" y "configurar esta imagen". – Alice

+0

@Alice Bueno, este fragmento de código es bastante similar a lo que haría bajo el capó si configuras uno de esos modos de contenido. En mis proyectos, normalmente utilizo el código anterior oculto detrás de alguna función o método global de fácil acceso (como una categoría en 'UIImage'), y luego cualquier escalado manual que necesito hacer es muy sencillo. –

+0

@justin Spahr-Summers, gracias, realmente funciona para mí. pero mi pregunta es ¿está trabajando con cualquier tamaño de imágenes? Pregunto sobre la percepción de imágenes HD y miniaturas. –

2

Dado que ninguno de mis intentos han trabajado ....

Tal vez se debería hacer esto en su lugar. Cuando se utiliza un UIButton:

Cuando DO Uso setImage en lugar de setBackgroundImage? (¿Por qué hay ambos?)

Cuando DO Uso "Aspect Fit" en lugar de "Center"? (¿Por qué ambos parecen estirar mis imágenes cuando espero que "mantengan la relación de aspecto" y "no cambien el tamaño nada", respectivamente)

Y la gran pregunta: ¿Por qué es algo tan común ... tal un gran desastre?

Todo se resolvería si pudiera encontrar un método alternativo como: simplemente use UIImage y detecte TAPS. (Pero eso parece ser incluso una pesadilla más GRANDE de código.)

Apple, si ha tratado de hacer mi trabajo más fácil ... en cambio, lo ha vuelto 400 veces más confuso.

6
UIImage *img = [UIImage imageNamed:@"yourImageName"]; 
button.imageView.contentMode = UIViewContentModeScaleAspectFit; 
[button setImage:img forState:UIControlStateNormal]; 
+0

Gracias por esta actualización. Para todas las demás personas que leyeron eso: ¡SÍ! En realidad, Apple parecía haber resuelto el problema de relación de aspec con UIButton. Y las "líneas de problemas" anteriores pueden saltarse por las pocas líneas de la respuesta anterior. – DerWOK

0

Me enfrenté al mismo problema hace unos días y lo resolvió. Por favor, trate con este

[_profilePicBtn setImage:profilePic forState:UIControlStateNormal]; 
_profilePicBtn.imageView.contentMode = UIViewContentModeScaleAspectFit; 
Cuestiones relacionadas