Как пропорционально масштабировать UIImageView?


341

У меня есть UIImageView, и цель состоит в том, чтобы пропорционально уменьшить его, задав ему высоту или ширину.

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;

Размер изображения был изменен, но позиция не в левом верхнем углу. Каков наилучший подход к масштабированию image / imageView и как мне исправить положение?


У меня есть что-то похожее на ваш код, который не работает для меня "UIImage * image = [UIImage imageNamed: imageString]; UIImageView * imageView = [[UIImage alloc] initWithImage: image];" создает исключение, которое убивает мое приложение, а это «Завершение приложения из-за необработанного исключения« NSInvalidArgumentException », причина:« - [UIImage initWithImage:]: нераспознанный селектор, отправленный экземпляру 0xd815930 »»
Spire

3
@Spire Это UIImageView, а не UIImage ^^
Томас Деко

2
Это работает для меня. Не забудьте установить .contentMode для вашего UIImageView, а не для вашего UIImage. - Вот мое: UIImageView * imageView = [[UIImageView alloc] initWithFrame: CGRectMake (0,0,30,30)]
Джаррет Барнетт

Ответы:


541

Исправлено легко, как только я нашел документацию!

 imageView.contentMode = UIViewContentModeScaleAspectFit;

19
Что вы на самом деле ответили? в вопросе Ронни он упомянул, что использует это
Dejell

3
Ваш imageView может не обрезать. Попробуйте imageView.layer.masksToBounds = YES;
Макворт

Сначала я попытался с IB убедиться, что он будет работать как нужно, но я не помню имя переменной для установки. Так я гуглю и нашел этот ответ.
Дино Тв

1
Для тех, у кого такая же проблема в Swift: ScaleAspectFitтеперь есть enum UIViewContentMode, так что вы бы установили imageView.contentMode = UIViewContentMode.ScaleAspectFit. Обратите внимание на период.
sudo make установить

1
translatesAutoresizingMaskIntoConstraintsне должен быть установлен в false. У меня ушло много времени, прежде чем я понял, что это свойство препятствует изменению размера
Джеральд

401

Я немного поговорил о типах масштабирования, поэтому решил собрать статью о некоторых наиболее популярных типах масштабирования в режиме контента .

Соответствующее изображение здесь:

введите описание изображения здесь


Как вы выравниваете по вертикали, когда установлен AspectFit?
esbenr

@esbenr Это должно произойти автоматически. Возможно, вам удастся найти переопределение по мере необходимости, но я пока не знаю его: |
Джексонкр,

Я хочу использовать Aspect Fill, но я также хочу отобразить полное изображение. Затем мне нужно изменить размер области под размер. Как я могу сделать это с автоматическим макетом?
Ли

@lee Есть несколько вариантов, но это действительно зависит от вашей ситуации. Я создал чат SOF, чтобы мы могли обсудить вашу тему, и я дам вам информацию, которая у меня есть, не стесняйтесь,
Джексонкр

@ Джексон Это не происходит автоматически вообще. Он выбирает высоту исходного изображения до того, как UIImageView масштабирует его, поэтому высота НЕ соответствует новой высоте по размеру. Если кто-нибудь найдет хороший способ сделать это, пожалуйста, дайте мне знать.
datWooWoo

78

Я только что попробовал это, и UIImage не поддерживает _imageScaledToSize.

В итоге я добавил метод в UIImage, используя категорию - предложение, которое я нашел на форумах Apple Dev.

В рамках всего проекта .h -

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

Реализация:

@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;

1
вместо того, чтобы UIGraphicsBeginImageContext(targetSize);делать, если ([UIScreen instancesRespondToSelector:@selector(scale)]) { UIGraphicsBeginImageContextWithOptions(targetSize, NO, 0.0f); } else { UIGraphicsBeginImageContext(targetSize); }поддерживать дисплеи сетчатки, не делая его размытым
велосипед


30

Вы можете попробовать сделать imageViewразмер, соответствующий image. Следующий код не проверен.

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;

1
установка imageView.frame = XXXX (что угодно) никак не отличается от вывода. есть идеи почему?
Срамым

1
@sramij Если вы используете autolayout, обязательно связывайтесь с [setTranslatesAutoResize ...] в UIViews. Если вы не знаете, что это значит, проверьте документацию! :)
datWooWoo

13

таким образом можно изменить размер UIImage

image = [UIImage imageWithCGImage:[image CGImage] scale:2.0 orientation:UIImageOrientationUp];

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]; 

Исходный код, размещенный сверху, хорошо работал для меня в iOS 4.2.

Я обнаружил, что создание CGRect и указание всех значений top, left, width и height было самым простым способом отрегулировать положение в моем случае, который использовал UIImageView внутри ячейки таблицы. (Еще нужно добавить код для освобождения объектов)



10

Это прекрасно работает для меня Swift 2.x:

imageView.contentMode = .ScaleAspectFill
imageView.clipsToBounds = true;



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

2

Я использовал следующий код. Где imageCoverView это UIView содержит 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;
}

2

Если предложенные здесь решения не работают для вас, и ваш актив изображения на самом деле представляет собой PDF, обратите внимание, что XCode на самом деле обрабатывает PDF иначе, чем файлы изображений. В частности, он не может масштабироваться для правильного заполнения PDF-файлом: вместо этого он оказывается мозаичным. Это сводило меня с ума, пока я не понял, что проблема была в формате PDF. Преобразование в JPG, и вы должны быть в порядке.


1

Обычно я использую этот метод для своих приложений ( 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
}

0

Я думаю, что вы можете сделать что-то вроде

image.center = [[imageView window] center];

3
Это не будет масштабировать изображение, а только отцентрировать его.
Дэвид Зальцер

-3

Вот как вы можете легко масштабировать его.

Это работает в 2.x с симулятором и iPhone.

UIImage *thumbnail = [originalImage _imageScaledToSize:CGSizeMake(40.0, 40.0) interpolationQuality:1];

привет, вы знаете, что делает параметр interpolationQuality: спасибо
user102008

27
Это недокументированный метод (подчеркивание - пустая распродажа), который может привести к отклонению приложения.
Shaggy Frog

Что делает параметр interpolationQuality?
lostInTransit
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.