Jak proporcjonalnie skalować UIImageView?


341

Mam UIImageView, a celem jest proporcjonalne zmniejszenie jego skali poprzez podanie jej wysokości lub szerokości.

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;

Rozmiar obrazu został zmieniony, ale pozycja nie znajduje się w lewym górnym rogu. Jakie jest najlepsze podejście do skalowania obrazu / obrazu i jak poprawić pozycję?


Mam coś podobnego do twojego kodu, który nie działa dla mnie "UIImage * image = [UIImage imageNamed: imageString]; UIImageView * imageView = [[Alokacja UIImage] initWithImage: image];" wykrywa wyjątek, który zabija moją aplikację za pomocą tego „Zamykanie aplikacji z powodu nieprzechwyconego wyjątku„ NSInvalidArgumentException ”, powód:„ - [UIImage initWithImage:]: nierozpoznany selektor wysłany do instancji 0xd815930 ””
Spire

3
@Spire It's UIImageView not UIImage ^^
Thomas Decaux

2
To działa dla mnie. Pamiętaj, aby ustawić .contentMode na UIImageView - nie na UIImage. - Oto moja: UIImageView * imageView = [[Alokacja UIImageView] initWithFrame: CGRectMake (0,0,30,30)]
Jarrett Barnett

Odpowiedzi:


541

Naprawiono łatwo, gdy znalazłem dokumentację!

 imageView.contentMode = UIViewContentModeScaleAspectFit;

19
Na co właściwie odpowiedziałeś? w pytaniu Ronniego wspomniał, że go używa
Dejell

3
Twój imageView może nie przycinać. Spróbuj imageView.layer.masksToBounds = TAK;
mackworth

Najpierw próbowałem z IB, aby upewnić się, że zadziała w razie potrzeby, ale nie pamiętam, aby ustawić nazwę zmiennej. Więc Google to i znalazłem tę odpowiedź.
Dino Tw

1
Dla każdego, kto ma ten sam problem w Swift: ScaleAspectFitjest teraz enum UIViewContentMode, więc ustawiłeś imageView.contentMode = UIViewContentMode.ScaleAspectFit. Zanotuj okres.
sudo dokonaj instalacji

1
translatesAutoresizingMaskIntoConstraintsnie powinien być ustawiony na false. Zajęło mi dużo czasu, zanim zdałem sobie sprawę, że ta właściwość uniemożliwia zmianę rozmiaru
Gerald

401

Widziałem trochę dyskusji na temat typów skalowania, dlatego postanowiłem przygotować artykuł dotyczący niektórych najpopularniejszych rodzajów skalowania w trybie zawartości .

Powiązany obraz jest tutaj:

wprowadź opis zdjęcia tutaj


Jak wyrównać w pionie po ustawieniu AspectFit?
esbenr

@esbenr Powinno to nastąpić automatycznie. W razie potrzeby możesz znaleźć zastąpienie, ale obecnie nie znam żadnego z nich: |
Jacksonkr,

Chcę użyć wypełnienia proporcji, ale chcę również wyświetlić pełny obraz. Następnie muszę zmienić rozmiar „Area to fit”. Jak mogę to zrobić z automatycznym układem?
Lee

@lee Istnieje wiele opcji, ale tak naprawdę zależy to od twojej sytuacji. Stworzyłem czat SOF, abyśmy mogli omówić twój temat, a dam ci informacje, które posiadam, przejdź
Jacksonkr

@Jackson To wcale nie dzieje się automatycznie. Wybiera wysokość oryginalnego obrazu przed skalowaniem go przez UIImageView, więc wysokość NIE odpowiada nowej wysokości dopasowanego kształtu. Jeśli ktoś wymyśli dobry sposób, aby to zrobić, daj mi znać.
datWooWoo

78

Właśnie próbowałem tego, a UIImage nie obsługuje _imageScaledToSize.

W końcu dodałem metodę do UIImage przy użyciu kategorii - sugestię znalazłem na forach Apple Dev.

W całym projekcie .h -

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

Realizacja:

@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
zamiast UIGraphicsBeginImageContext(targetSize);zrobić, jeśli ([UIScreen instancesRespondToSelector:@selector(scale)]) { UIGraphicsBeginImageContextWithOptions(targetSize, NO, 0.0f); } else { UIGraphicsBeginImageContext(targetSize); }ma obsługiwać wyświetlacze siatkówki bez powodowania rozmycia
rower

38
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.clipsToBounds = YES;

30

Możesz spróbować imageViewdopasować rozmiar do image. Poniższy kod nie jest testowany.

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
ustawienie imageView.frame = XXXX (cokolwiek) nie różni się niczym od wyniku. jakiś pomysł dlaczego?
sramij

1
@sramij Jeśli używasz autolayout, upewnij się, że zadzierasz z [setTranslatesAutoResize ...] na UIViews. Jeśli nie wiesz, co to takiego, sprawdź dokumentację! :)
datWooWoo

13

w ten sposób można zmienić rozmiar 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]; 

Oryginalny kod opublikowany na górze działał dla mnie dobrze w iOS 4.2.

Odkryłem, że utworzenie CGRect i określenie wszystkich wartości górnej, lewej, szerokości i wysokości było najłatwiejszym sposobem dostosowania pozycji w moim przypadku, który wykorzystywał UIImageView w komórce tabeli. (Nadal trzeba dodać kod, aby zwolnić obiekty)



10

To działa dobrze dla mnie 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

Użyłem następującego kodu. Gdzie imageCoverView to UIView zawiera 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

Jeśli zaproponowane tutaj rozwiązania nie działają, a Twoim zasobem obrazu jest w rzeczywistości plik PDF, zauważ, że XCode tak naprawdę traktuje pliki PDF inaczej niż pliki obrazów. W szczególności nie wydaje się być w stanie skalować, aby poprawnie wypełnić plik PDF: zamiast tego kończy się kafelkami. Doprowadzało mnie to do szału, dopóki nie zorientowałem się, że chodziło o format PDF. Konwertuj na JPG i powinieneś być gotowy.


1

Zwykle używam tej metody do moich aplikacji ( kompatybilnych z 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
}


-3

Oto, jak możesz łatwo to skalować.

Działa to w wersji 2.x z symulatorem i telefonem iPhone.

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

cześć, czy wiesz, co robi parametr interpolationQuality:? dzięki
użytkownik102008,

27
Jest to nieudokumentowana metoda (podkreślenie jest martwą gracją), która może spowodować odrzucenie aplikacji.
Shaggy Frog

Do czego służy parametr interpolationQuality?
lostInTransit
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.