¿Cómo escalar un UIImageView proporcionalmente?

341

Tengo un UIImageView y el objetivo es reducirlo proporcionalmente dándole altura o ancho.

UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://farm4.static.flickr.com/3092/2915896504_a88b69c9de.jpg"]]];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; 

//Add image view
[self.view addSubview:imageView];   

//set contentMode to scale aspect to fit
imageView.contentMode = UIViewContentModeScaleAspectFit;

//change width of frame
CGRect frame = imageView.frame;
frame.size.width = 100;
imageView.frame = frame;

La imagen se redimensionó pero la posición no está en la esquina superior izquierda. ¿Cuál es el mejor enfoque para escalar image / imageView y cómo corrijo la posición?

Ronnie Liew
fuente
Tengo algo similar a su código que no funciona para mí "UIImage * image = [UIImage imageNamed: imageString]; UIImageView * imageView = [[UIImage alloc] initWithImage: image];" muestra una excepción que mata mi aplicación con esta "Aplicación finalizada debido a la excepción no detectada 'NSInvalidArgumentException', razón: '- [UIImage initWithImage:]: selector no reconocido enviado a la instancia 0xd815930'"
Spire
3
@Spire Es UIImageView no UIImage ^^
Thomas Decaux
2
Esto funciona para mi. Recuerde configurar .contentMode en su UIImageView, no en su UIImage. - Aquí está el mío: UIImageView * imageView = [[UIImageView alloc] initWithFrame: CGRectMake (0,0,30,30)]
Jarrett Barnett

Respuestas:

541

Solucionado fácilmente, una vez que encontré la documentación!

 imageView.contentMode = UIViewContentModeScaleAspectFit;
Ken Abrams
fuente
19
¿Qué respondiste realmente? En la pregunta de Ronnie, mencionó que lo usa
Dejell
3
Su imageView puede no ser recorte. Pruebe imageView.layer.masksToBounds = YES;
mackworth
Primero intenté con IB para asegurarme de que funcionaría según sea necesario, pero no recuerdo el nombre de la variable para establecer. Así que lo busqué en Google y encontré esta respuesta.
Dino Tw
1
Para cualquiera que tenga el mismo problema en Swift: ScaleAspectFitahora es un enum UIViewContentMode, así que debería configurarlo imageView.contentMode = UIViewContentMode.ScaleAspectFit. Tenga en cuenta el período.
sudo make install
1
translatesAutoresizingMaskIntoConstraintsno debe ser ajustado a false. Me tomó mucho tiempo antes de darme cuenta de que esta propiedad está impidiendo el cambio de tamaño
Gerald
401

He visto un poco de conversación sobre los tipos de escala, así que decidí armar un artículo sobre algunos de los tipos de escala de modo de contenido más populares .

La imagen asociada está aquí:

ingrese la descripción de la imagen aquí

Jacksonkr
fuente
¿Cómo se alinea verticalmente cuando se configura AspectFit?
esbenr
@esbenr Eso debería suceder automáticamente. Es posible que pueda encontrar una anulación según sea necesario, pero no sé de una actualmente: |
Jacksonkr
Quiero usar Aspect Fill pero también quiero mostrar la imagen completa. Entonces necesito cambiar el tamaño de 'Área para ajustar'. ¿Cómo puedo hacer esto con el diseño automático?
lee
@lee Hay varias opciones, pero depende mucho de tu situación. He creado un chat SOF para que podamos discutir su tema y le daré la información que quiero, vaya si lo desea: chat.stackoverflow.com/rooms/81180/ios-autoresize-chat
Jacksonkr
@Jackson Eso no sucede automáticamente en absoluto. Elige la altura de la imagen original antes de que el UIImageView la escale, por lo que la altura NO coincide con la nueva altura de Aspecto ajustado. Si alguien descubre una buena manera de hacer esto, hágamelo saber.
datWooWoo
78

Acabo de probar esto y UIImage no es compatible con _imageScaledToSize.

Terminé agregando un método a UIImage usando una categoría, una sugerencia que encontré en los foros de Apple Dev.

En un proyecto .h -

@interface UIImage (Extras)
- (UIImage *)imageByScalingProportionallyToSize:(CGSize)targetSize;
@end;

Implementación:

@implementation UIImage (Extras)

- (UIImage *)imageByScalingProportionallyToSize:(CGSize)targetSize {

    UIImage *sourceImage = self;
    UIImage *newImage = nil;

    CGSize imageSize = sourceImage.size;
    CGFloat width = imageSize.width;
    CGFloat height = imageSize.height;

    CGFloat targetWidth = targetSize.width;
    CGFloat targetHeight = targetSize.height;

    CGFloat scaleFactor = 0.0;
    CGFloat scaledWidth = targetWidth;
    CGFloat scaledHeight = targetHeight;

    CGPoint thumbnailPoint = CGPointMake(0.0,0.0);

    if (CGSizeEqualToSize(imageSize, targetSize) == NO) {

        CGFloat widthFactor = targetWidth / width;
        CGFloat heightFactor = targetHeight / height;

        if (widthFactor < heightFactor) 
            scaleFactor = widthFactor;
        else
            scaleFactor = heightFactor;

        scaledWidth  = width * scaleFactor;
        scaledHeight = height * scaleFactor;

        // center the image

        if (widthFactor < heightFactor) {
            thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; 
        } else if (widthFactor > heightFactor) {
            thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
        }
    }


    // this is actually the interesting part:

    UIGraphicsBeginImageContext(targetSize);

    CGRect thumbnailRect = CGRectZero;
    thumbnailRect.origin = thumbnailPoint;
    thumbnailRect.size.width  = scaledWidth;
    thumbnailRect.size.height = scaledHeight;

    [sourceImage drawInRect:thumbnailRect];

    newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    if(newImage == nil) NSLog(@"could not scale image");


    return newImage ;
}

@end;
Jane Sales
fuente
1
en lugar de UIGraphicsBeginImageContext(targetSize);hacerlo si ([UIScreen instancesRespondToSelector:@selector(scale)]) { UIGraphicsBeginImageContextWithOptions(targetSize, NO, 0.0f); } else { UIGraphicsBeginImageContext(targetSize); }es compatible con pantallas de retina sin hacerlo borroso
bicicleta
38
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.clipsToBounds = YES;
Li-chih Wu
fuente
30

Podrías intentar hacer que el imageViewtamaño coincida con el image. El siguiente código no se prueba.

CGSize kMaxImageViewSize = {.width = 100, .height = 100};
CGSize imageSize = image.size;
CGFloat aspectRatio = imageSize.width / imageSize.height;
CGRect frame = imageView.frame;
if (kMaxImageViewSize.width / aspectRatio <= kMaxImageViewSize.height) 
{
    frame.size.width = kMaxImageViewSize.width;
    frame.size.height = frame.size.width / aspectRatio;
} 
else 
{
    frame.size.height = kMaxImageViewSize.height;
    frame.size.width = frame.size.height * aspectRatio;
}
imageView.frame = frame;
Chris Lundie
fuente
1
configurar imageView.frame = XXXX (cualquier cosa) no hace ninguna diferencia en la salida. alguna idea de por qué?
sramij
1
@sramij Si está utilizando autolayout, asegúrese de meterse con [setTranslatesAutoResize ...] en las UIViews. ¡Si no sabe qué hace, consulte la documentación! :)
datWooWoo
13

uno puede cambiar el tamaño de un UIImage de esta manera

image = [UIImage imageWithCGImage:[image CGImage] scale:2.0 orientation:UIImageOrientationUp];
neoneye
fuente
13
UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://farm4.static.flickr.com/3092/2915896504_a88b69c9de.jpg"]]];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; 


//set contentMode to scale aspect to fit
imageView.contentMode = UIViewContentModeScaleAspectFit;

//change width of frame
//CGRect frame = imageView.frame;
//frame.size.width = 100;
//imageView.frame = frame;

//original lines that deal with frame commented out, yo.
imageView.frame = CGRectMake(10, 20, 60, 60);

...

//Add image view
[myView addSubview:imageView]; 

El código original publicado en la parte superior funcionó bien para mí en iOS 4.2.

Descubrí que crear un CGRect y especificar todos los valores superior, izquierdo, ancho y alto era la forma más fácil de ajustar la posición en mi caso, que estaba usando un UIImageView dentro de una celda de la tabla. (Todavía es necesario agregar código para liberar objetos)

Nate Flink
fuente
13

Configure su ImageView seleccionando Modo en Aspect Filly marque la Clip Subviewscasilla.

ingrese la descripción de la imagen aquí

Jeffrey Neo
fuente
10

Esto funciona bien para mí Swift 2.x:

imageView.contentMode = .ScaleAspectFill
imageView.clipsToBounds = true;
vvamondes
fuente
9

Establezca su UIimageviewpor escala .........

ingrese la descripción de la imagen aquí

PJRadadiya
fuente
6

Para Swift:

self.imageViews.contentMode = UIViewContentMode.ScaleToFill
Somir Saikia
fuente
5

UIImageView + Scale.h:

#import <Foundation/Foundation.h>

@interface UIImageView (Scale)

-(void) scaleAspectFit:(CGFloat) scaleFactor;

@end

UIImageView + Scale.m:

#import "UIImageView+Scale.h"

@implementation UIImageView (Scale)


-(void) scaleAspectFit:(CGFloat) scaleFactor{

    self.contentScaleFactor = scaleFactor;
    self.transform = CGAffineTransformMakeScale(scaleFactor, scaleFactor);

    CGRect newRect = self.frame;
    newRect.origin.x = 0;
    newRect.origin.y = 0;
    self.frame = newRect;
}

@end
Peter Kreinz
fuente
2

Usé el siguiente código. Donde imageCoverView es UIView contiene UIImageView

if (image.size.height<self.imageCoverView.bounds.size.height && image.size.width<self.imageCoverView.bounds.size.width)
{
    [self.profileImageView sizeToFit];
    self.profileImageView.contentMode =UIViewContentModeCenter
}
else
{
    self.profileImageView.contentMode =UIViewContentModeScaleAspectFit;
}
Avijit Nagare
fuente
2

Si las soluciones propuestas aquí no funcionan para usted, y su recurso de imagen es en realidad un PDF, tenga en cuenta que XCode realmente trata los PDF de manera diferente a los archivos de imagen. En particular, no parece capaz de escalar para rellenar correctamente con un PDF: en su lugar, termina en mosaico. Esto me volvió loco hasta que descubrí que el problema era el formato PDF. Convierte a JPG y deberías estar listo.

Lane Rettig
fuente
1

Por lo general, uso este método para mis aplicaciones ( compatible con Swift 2.x ):

// Resize UIImage
func resizeImage(image:UIImage, scaleX:CGFloat,scaleY:CGFloat) ->UIImage {
    let size = CGSizeApplyAffineTransform(image.size, CGAffineTransformMakeScale(scaleX, scaleY))
    let hasAlpha = true
    let scale: CGFloat = 0.0 // Automatically use scale factor of main screen

    UIGraphicsBeginImageContextWithOptions(size, !hasAlpha, scale)
    image.drawInRect(CGRect(origin: CGPointZero, size: size))

    let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return scaledImage
}
Alessandro Ornano
fuente
0

Creo que puedes hacer algo como

image.center = [[imageView window] center];
usuario26359
fuente
3
No escalará la imagen sino que solo la centrará.
David Salzer
-3

Aquí es cómo puedes escalarlo fácilmente.

Esto funciona en 2.x con el simulador y el iPhone.

UIImage *thumbnail = [originalImage _imageScaledToSize:CGSizeMake(40.0, 40.0) interpolationQuality:1];
kdbdallas
fuente
hola, ¿sabes qué hace el parámetro interpolationQuality:? gracias
user102008
27
Este es un método no documentado (el guión bajo es un sorteo) que podría provocar el rechazo de la aplicación.
Shaggy Frog
¿Qué hace el parámetro interpolationQuality?
lostIn tránsito