Как пропорционально масштабировать 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

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

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

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

Jacksonkr
источник
Как вы выравниваете по вертикали, когда установлен 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); }поддерживать дисплеи сетчатки, не делая его размытым
велосипед
38
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.clipsToBounds = YES;
Ли Чжи Ву
источник
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];
neoneye
источник
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 внутри ячейки таблицы. (Еще нужно добавить код для освобождения объектов)

Нейт Флинк
источник
13

Установите ImageView, выбрав Mode Aspect Fillи установите Clip Subviewsфлажок.

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

Джеффри Нео
источник
10

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

imageView.contentMode = .ScaleAspectFill
imageView.clipsToBounds = true;
vvamondes
источник
9

Установите свой UIimageviewмасштаб .........

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

PJRadadiya
источник
6

Для Свифта:

self.imageViews.contentMode = UIViewContentMode.ScaleToFill
Сомир Сайкия
источник
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];
user26359
источник
3
Это не будет масштабировать изображение, а только отцентрировать его.
Дэвид Зальцер
-3

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

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

UIImage *thumbnail = [originalImage _imageScaledToSize:CGSizeMake(40.0, 40.0) interpolationQuality:1];
kdbdallas
источник
привет, вы знаете, что делает параметр interpolationQuality: спасибо
user102008
27
Это недокументированный метод (подчеркивание - пустая распродажа), который может привести к отклонению приложения.
Shaggy Frog
Что делает параметр interpolationQuality?
lostInTransit