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ę?

Ronnie Liew
źródło
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;
Ken Abrams
źródło
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

Jacksonkr
źródło
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;
Jane Sales
źródło
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;
Li-chih Wu
źródło
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;
Chris Lundie
źródło
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];
neoneye
źródło
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)

Nate Flink
źródło
13

Ustaw ImageView, wybierając Tryb Aspect Filli zaznaczając Clip Subviewspole.

wprowadź opis zdjęcia tutaj

Jeffrey Neo
źródło
10

To działa dobrze dla mnie Swift 2.x:

imageView.contentMode = .ScaleAspectFill
imageView.clipsToBounds = true;
vvamondes
źródło
9

Ustaw UIimageviewwedług skali .........

wprowadź opis zdjęcia tutaj

PJRadadiya
źródło
6

Dla Swift:

self.imageViews.contentMode = UIViewContentMode.ScaleToFill
Somir Saikia
źródło
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
źródło
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;
}
Avijit Nagare
źródło
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.

Lane Rettig
źródło
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
}
Alessandro Ornano
źródło
0

Myślę, że możesz zrobić coś takiego

image.center = [[imageView window] center];
użytkownik26359
źródło
3
Nie będzie skalować obrazu, a jedynie wyśrodkować go.
David Salzer
-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];
kdbdallas
źródło
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