Como dimensionar um UIImageView proporcionalmente?

341

Eu tenho um UIImageView e o objetivo é reduzi-lo proporcionalmente, fornecendo uma altura ou largura.

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;

A imagem foi redimensionada, mas a posição não está no canto superior esquerdo. Qual é a melhor abordagem para dimensionar image / imageView e como faço para corrigir a posição?

Ronnie Liew
fonte
Eu tenho algo semelhante ao seu código que não funciona para mim "UIImage * image = [UIImage imageNamed: imageString]; UIImageView * imageView = [[UIImage alocado] initWithImage: image];" trows uma exceção que mata meu aplicativo com este "Aplicativo de encerramento devido à exceção não capturada 'NSInvalidArgumentException', motivo: '- [UIImage initWithImage:]: seletor não reconhecido enviado para a instância 0xd815930'"
Spire em
3
De @Spire Ele UIImageView não UIImage ^^
Thomas Decaux
2
Isso funciona para mim. Lembre-se de definir o .contentMode como seu UIImageView - e não seu UIImage. - Aqui é minha: UIImageView * imageView = [[UIImageView alloc] initWithFrame: CGRectMake (0,0,30,30)]
Jarrett Barnett

Respostas:

541

Corrigido facilmente, uma vez que encontrei a documentação!

 imageView.contentMode = UIViewContentModeScaleAspectFit;
Ken Abrams
fonte
19
O que você realmente respondeu? na pergunta de Ronnie, ele mencionou que o usa
Dejell
3
O seu imageView pode não estar cortando. Tente imageView.layer.masksToBounds = YES;
mackworth
Primeiro tentei com o IB para garantir que funcionasse conforme necessário, mas não me lembro do nome da variável a ser definida. Então, pesquisei no Google e encontrei esta resposta.
Dino Tw
11
Para quem tem o mesmo problema no Swift: ScaleAspectFitagora é um enum UIViewContentMode, então você deve definir imageView.contentMode = UIViewContentMode.ScaleAspectFit. Observe o período.
sudo make install
11
translatesAutoresizingMaskIntoConstraintsnão deve ser definido como false. Levei um longo tempo antes de perceber que esta propriedade está impedindo o redimensionamento
Gerald
401

Como conversei um pouco sobre tipos de escala, decidi montar um artigo sobre alguns dos tipos de escala de modo de conteúdo mais populares .

A imagem associada está aqui:

insira a descrição da imagem aqui

Jacksonkr
fonte
Como você se alinha quando o AspectFit está definido?
esbenr
@ esbenr Isso deve acontecer automaticamente. Você pode encontrar uma substituição conforme necessário, mas não conheço uma atualmente: |
Jacksonkr
Quero usar o Aspect Fill, mas também quero exibir a imagem completa. Então eu preciso alterar o tamanho da 'Área para caber'. Como posso fazer isso com o layout automático?
Lee
@lee Há várias opções, mas é realmente dependente da sua situação. Eu criei um bate-papo SOF para que possamos discutir seu tópico e darei a você as informações que tenho, de cabeça para baixo
Jacksonkr
@ Jackson Isso não acontece automaticamente. Ele escolhe a altura da imagem original antes que o UIImageView a dimensione, para que a altura NÃO corresponda à nova altura ajustada por aspecto. Se alguém descobrir uma boa maneira de fazer isso, entre em contato.
datWooWoo
78

Eu apenas tentei isso e o UIImage não suporta _imageScaledToSize.

Acabei adicionando um método ao UIImage usando uma categoria - uma sugestão que encontrei nos fóruns de desenvolvedores da Apple.

Em um .h de todo o projeto -

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

Implementação:

@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
fonte
11
em vez de UIGraphicsBeginImageContext(targetSize);fazer se ([UIScreen instancesRespondToSelector:@selector(scale)]) { UIGraphicsBeginImageContextWithOptions(targetSize, NO, 0.0f); } else { UIGraphicsBeginImageContext(targetSize); }para suportar telas Retina sem torná-lo desfocadas
bicicleta
38
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.clipsToBounds = YES;
Li-chih Wu
fonte
30

Você pode tentar fazer o imageViewtamanho corresponder ao image. O código a seguir não foi testado.

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
fonte
11
definir imageView.frame = XXXX (qualquer coisa) não faz diferença na saída. Alguma idéia do porquê?
sramij
11
@sramij Se você estiver usando o autolayout, certifique-se de mexer com [setTranslatesAutoResize ...] nas UIViews. Se você não sabe o que isso faz, verifique a documentação! :)
datWooWoo
13

pode-se redimensionar uma UIImage dessa maneira

image = [UIImage imageWithCGImage:[image CGImage] scale:2.0 orientation:UIImageOrientationUp];
neoneye
fonte
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]; 

O código original publicado na parte superior funcionou bem para mim no iOS 4.2.

Descobri que criar um CGRect e especificar todos os valores superior, esquerdo, largura e altura era a maneira mais fácil de ajustar a posição no meu caso, que estava usando um UIImageView dentro de uma célula da tabela. (Ainda é necessário adicionar código para liberar objetos)

Nate Flink
fonte
13

Defina seu ImageView selecionando Modo para Aspect Fille marque a Clip Subviewscaixa.

insira a descrição da imagem aqui

Jeffrey Neo
fonte
10

Isso funciona bem para mim Swift 2.x:

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

Defina o seu UIimageviewpor escala .........

insira a descrição da imagem aqui

PJRadadiya
fonte
6

Para Swift:

self.imageViews.contentMode = UIViewContentMode.ScaleToFill
Somir Saikia
fonte
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
fonte
2

Eu usei o seguinte código.where imageCoverView is UIView segura 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
fonte
2

Se as soluções propostas aqui não estiverem funcionando para você e seu ativo de imagem for realmente um PDF, observe que o XCode realmente trata os PDFs de maneira diferente dos arquivos de imagem. Em particular, ele não parece escalável para preencher corretamente com um PDF: acaba sendo lado a lado. Isso me deixou louco até eu descobrir que o problema era o formato PDF. Converta em JPG e você deve estar pronto.

Lane Rettig
fonte
1

Normalmente, eu uso esse método para meus aplicativos (compatível com 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
fonte
0

Eu acho que você pode fazer algo como

image.center = [[imageView window] center];
user26359
fonte
3
Não dimensionará a imagem, mas apenas a centralizará.
David Salzer 17/02
-3

Aqui está como você pode dimensioná-lo facilmente.

Isso funciona na versão 2.x com o simulador e o iPhone.

UIImage *thumbnail = [originalImage _imageScaledToSize:CGSizeMake(40.0, 40.0) interpolationQuality:1];
kdbdallas
fonte
oi, você sabe o que faz o parâmetro interpolationQuality:? graças
user102008
27
Este é um método não documentado (o sublinhado é uma oferta inoperante) que pode resultar na rejeição do aplicativo.
Shaggy Frog
O que o parâmetro interpolationQuality faz?
precisa saber é o seguinte