UIImageView dopasowanie obrazu i wyśrodkowanie

183

Mam widok obrazu zadeklarowany programowo i ustawiam jego obraz również programowo.

Jednak nie jestem w stanie ustawić obrazu tak, aby pasował do aspektu i wyrównał środek do widoku obrazu.

Innymi słowy, chcę, aby obraz:

  • Skaluj w dół, aby dopasować do formatu, jeśli obraz jest duży.
  • Wyśrodkuj, ale nie skaluj w górę, jeśli obraz jest mały.

Jak mogę to zdobyć?

Ravi Vooda
źródło
19
[yourImageView setContentMode: UIViewContentModeCenter]; i upewnij się, że imageView Frame jest większy niż frame obrazu. jeśli nie, umieść [yourImageView setContentMode: UIViewContentModeAspectToFit];
Manohar Perepa
1
jeśli jeszcze warunek koleś @RyanPoolos
Manohar Perepa

Odpowiedzi:

205

Wklejanie rozwiązania:

Tak jak powiedział @manohar

imageView.contentMode = UIViewContentModeCenter;
if (imageView.bounds.size.width > ((UIImage*)imagesArray[i]).size.width && imageView.bounds.size.height > ((UIImage*)imagesArray[i]).size.height) {
       imageView.contentMode = UIViewContentModeScaleAspectFit;
}

rozwiązał mój problem

Ravi Vooda
źródło
7
Krótszy sposób na znalezienie obrazu jest mniejszy:CGRectContainsRect(imageView.bounds, {CGPointZero, image.size})
Por.
@ Cfr może jest krótszy, ale nie tak czytelny. Jednocześnie proponuję, aby podzielić linię z if-oświadczenie takie jak to: CGSize imageSize = ((UIImage*)imagesArray[i]).size;, CGSize viewSize = imageView.bounds.size, if (viewSize.width > imageSize.width && viewSize.height > imageSize.height) {.
Timur Bernikowicz
1
Powinien być UIViewContentModeScaleAspectFit
NoelHunter
imageView.contentMode = UIViewContentModeScaleAspectFit;
Arjay Waran
75

W szybkim języku możemy ustawić tryb zawartości widoku UIImage w następujący sposób:

let newImgThumb = UIImageView(frame: CGRect(x: 10, y: 10, width: 100, height: 100))
newImgThumb.contentMode = .scaleAspectFit
Ali Raza
źródło
3
Powoduje to wysadzenie obrazu, jeśli jest mniejszy niż widok obrazu, w przeciwieństwie do tego, o co poprosił PO.
fishinear
17

Szybki

yourImageView.contentMode = .center

Do pozycjonowania obrazu możesz użyć następujących opcji:

  • scaleToFill
  • scaleAspectFit // zawartość skalowana w celu dopasowania do stałego aspektu. reszta jest przezroczysta
  • redraw // przerysuj przy zmianie granic (połączenia -setNeedsDisplay)
  • center// zawartość pozostaje tego samego rozmiaru. ustawiony skorygowany.
  • top
  • bottom
  • left
  • right
  • topLeft
  • topRight
  • bottomLeft
  • bottomRight
Jonas Deichelmann
źródło
12

Zaktualizowana odpowiedź

Kiedy pierwotnie odpowiedziałem na to pytanie w 2014 r., Nie było wymogu, aby nie skalować obrazu w przypadku małego obrazu. (Pytanie zostało zredagowane w 2015 r .) Jeśli masz takie wymaganie, rzeczywiście musisz porównać rozmiar obrazu z rozmiarem imageView i użyć albo UIViewContentModeCenter(w przypadku obrazu mniejszego niż imageView) lub UIViewContentModeScaleAspectFitwe wszystkich innych przypadkach .

Oryginalna odpowiedź

Ustawienie contentMode dla imageView UIViewContentModeScaleAspectFitbyło dla mnie wystarczające. Wydaje się również, że obrazy są w środku. Nie jestem pewien, dlaczego inni używają logiki opartej na obrazie. Zobacz także to pytanie: dopasowanie i wyśrodkowanie w systemie iOS

Nate Cook
źródło
1
Powoduje to wysadzenie obrazu, jeśli jest mniejszy niż widok obrazu, w przeciwieństwie do tego, o co poprosił PO.
fishinear
1
@fishinear Wymaganie dotyczące nieskalowania obrazu zostało dodane do pytania rok po tym, jak odpowiedziałem: stackoverflow.com/posts/15499376/revisions
Nate Cook
10

Tak rozwiązałem ten problem.

  1. setImage na UIImageView(z UIViewContentModeScaleAspectFit)
  2. pobierz imageSize (CGSize imageSize = imageView.image.size)
  3. UIImageView Zmień rozmiar. [imageView sizeThatFits:imageSize]
  4. przesuń pozycję, gdzie chcesz.

Chciałem umieścić UIView na najwyższym środku UICollectionViewCell. więc użyłem tej funkcji.

- (void)setImageToCenter:(UIImageView *)imageView
{
    CGSize imageSize = imageView.image.size;
    [imageView sizeThatFits:imageSize];
    CGPoint imageViewCenter = imageView.center;
     imageViewCenter.x = CGRectGetMidX(self.contentView.frame);
    [imageView setCenter:imageViewCenter];
}

Mi to pasuje.

Nicejinux
źródło
8

Ta podklasa używa środka, jeśli obraz nie jest większy niż widok, w przeciwnym razie skaluje się. Uważam, że jest to przydatne w przypadku UIImageViewzmiany rozmiaru.

Obraz, który wyświetla, jest mniejszy niż widok dla dużych rozmiarów, ale większy niż widok dla małych rozmiarów. Chcę, żeby to się zmniejszyło, ale nie w górę.

class CenterScaleToFitImageView: UIImageView {
    override var bounds: CGRect {
        didSet {
            adjustContentMode()
        }
    }

    override var image: UIImage? {
        didSet {
            adjustContentMode()
        }
    }

    func adjustContentMode() {
        guard let image = image else {
            return
        }
        if image.size.width > bounds.size.width ||
            image.size.height > bounds.size.height {
            contentMode = .ScaleAspectFit
        } else {
            contentMode = .Center
        }
    }
}
orkoden
źródło
8

Można to osiągnąć, ustawiając tryb zawartości widoku obrazu na UIViewContentModeScaleAspectFill.

Następnie użyj następującej metody metody, aby uzyskać obiekt uiimage o zmienionym rozmiarze.

- (UIImage*)setProfileImage:(UIImage *)imageToResize onImageView:(UIImageView *)imageView
{
    CGFloat width = imageToResize.size.width;
    CGFloat height = imageToResize.size.height;
    float scaleFactor;
    if(width > height)
    {
        scaleFactor = imageView.frame.size.height / height;
    }
    else
    {
        scaleFactor = imageView.frame.size.width / width;
    }

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(width * scaleFactor, height * scaleFactor), NO, 0.0);
    [imageToResize drawInRect:CGRectMake(0, 0, width * scaleFactor, height * scaleFactor)];
    UIImage *resizedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return resizedImage;
}

Edytowano tutaj (wersja Swift)

func setProfileImage(imageToResize: UIImage, onImageView: UIImageView) -> UIImage
{
    let width = imageToResize.size.width
    let height = imageToResize.size.height

    var scaleFactor: CGFloat

    if(width > height)
    {
        scaleFactor = onImageView.frame.size.height / height;
    }
    else
    {
        scaleFactor = onImageView.frame.size.width / width;
    }

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(width * scaleFactor, height * scaleFactor), false, 0.0)
    imageToResize.drawInRect(CGRectMake(0, 0, width * scaleFactor, height * scaleFactor))
    let resizedImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return resizedImage;
}
Manish
źródło
7
[your_imageview setContentMode:UIViewContentModeCenter];
souvickcse
źródło
17
To zignoruje skalowanie
Skrew
2
Nie wiem, dlaczego takie rozwiązania mają tak wiele pozytywnych opinii. Ta osoba w ogóle nie przeczytała pytania.
wolny
7
let bannerImageView = UIImageView();
bannerImageView.contentMode = .ScaleAspectFit;
bannerImageView.frame = CGRectMake(cftX, cftY, ViewWidth, scrollHeight);
Antony Ouseph
źródło
Powoduje to wysadzenie obrazu, jeśli jest mniejszy niż widok obrazu, w przeciwieństwie do tego, o co poprosił PO.
fishinear
2

Dla osób szukających zmiany rozmiaru UIImage,

@implementation UIImage (Resize)

- (UIImage *)scaledToSize:(CGSize)size
{
    UIGraphicsBeginImageContextWithOptions(size, NO, 0.0f);
    [self drawInRect:CGRectMake(0.0f, 0.0f, size.width, size.height)];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

- (UIImage *)aspectFitToSize:(CGSize)size
{
    CGFloat aspect = self.size.width / self.size.height;
    if (size.width / aspect <= size.height)
    {
        return [self scaledToSize:CGSizeMake(size.width, size.width / aspect)];
    } else {
        return [self scaledToSize:CGSizeMake(size.height * aspect, size.height)];
    }
}

- (UIImage *)aspectFillToSize:(CGSize)size
{
    CGFloat imgAspect = self.size.width / self.size.height;
    CGFloat sizeAspect = size.width/size.height;

    CGSize scaledSize;

        if (sizeAspect > imgAspect) { // increase width, crop height
            scaledSize = CGSizeMake(size.width, size.width / imgAspect);
        } else { // increase height, crop width
            scaledSize = CGSizeMake(size.height * imgAspect, size.height);
        }
    UIGraphicsBeginImageContextWithOptions(size, NO, 0.0f);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextClipToRect(context, CGRectMake(0, 0, size.width, size.height));
    [self drawInRect:CGRectMake(0.0f, 0.0f, scaledSize.width, scaledSize.height)];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

@end
karim
źródło