UIViewContentModeScaleAspectFill nie przycina


144

Próbuję narysować kilka miniatur o stałym rozmiarze (100x100) za pomocą UIImageView. Mam ustawić rozmiar ramki obrazu moim zdaniem być 100x100 i ustaw contentModesię UIViewContentModeScaleAspectFill.

Rozumiem, że powinno to spowodować, że obraz zostanie narysowany w ustawionym przeze mnie rozmiarze, a obraz wypełni obszar obrazu i przycina wszystkie części obrazu, które wykraczają poza rozmiar, który ustawiłem dla widoku obrazu. Jednak obraz jest nadal większy lub mniejszy niż rozmiar 100x100, który dla niego ustawiłem.

Jeżeli ustawić contentModesię UIviewContentModeScaleToFill, a następnie obraz jest rysowany dokładnie 100x100, ale jest zniekształcony, aby pasowały do tych wymiarów. Jakieś pomysły, dlaczego wypełnienie aspektu nie jest przycinane zgodnie z oczekiwaniami?

Oto mój kod:

_photoView = [[UIImageView alloc] initWithImage:photoImage];
_photoView.contentMode = UIViewContentModeScaleAspectFill;
[self addSubview:_photoView];

CGRect photoFrame = _photoView.frame;
photoFrame.size = CGSizeMake(100, 100);
_photoView.frame = photoFrame;

Aby lepiej zilustrować, oto zrzut ekranu tego, co widzę. Zielone kwadraty UIViewzawierają elementy, z UIImageViewktórymi pracuję. Ustawiłem ich kolor tła na zielony, a ramkę widoku na 100x100. W teście, UIImageViewsmają wymiary 50x50. Jak widać, w przypadku korzystania z ...AspectFillobrazu obrazy nie mają rozmiaru 50x50, a w niektórych przypadkach są przesunięte w stosunku do tego, co chciałbym. Podczas używania ...ScaleToFillmają prawidłowe rozmiary, ale obraz jest zniekształcony.

Zrzut ekranu ilustrujący problem

Odpowiedzi:


352

Czy możesz spróbować ustawić klip do granic

[_photoview setClipsToBounds:YES];

Lub bezpośrednio w swoim Storyboard / Xib, jeśli możesz:

wprowadź opis obrazu tutaj


10
To było to - dzięki. (Dodałem powyższym zrzucie ekranu, aby lepiej pokazać, co widziałem, bardziej jako przykład, jeśli ktoś przychodzi całej tej kwestii.)
Josh Buhler

3
W InterfaceBuilder zmieniono nazwę (nieprzydatnie) na „Clips subviews” (uwaga: w tym przypadku nie clib „subviews”, nazwa jest nieprawidłowa: przycina SELF AND subviews)
Adam

3
Zaznaczenie opcji „Clip Subviews” w pliku NIB robi to samo. Twoje zdrowie.
codeburn

Ale co jeśli chcesz dodać cień za pomocą właściwości CALayer :( dodanie innego widoku za nim nie jest dla mnie idealne
Rambatino

Jeśli używasz Auto Layout, tak jak ja, istnieje inna możliwa przyczyna, a mianowicie NSLayoutConstraint „UIView-Encapsulated-Layout-Height” łamiąc ograniczenia rozmiaru UIImageView.
ewiinnnnn

8

Jeśli chcesz poszerzyć swoją wiedzę, jest naprawdę dobry artykuł o tym, jak renderowany jest stos iOS UIView . Istnieje również bardziej szczegółowy artykuł na temat całego procesu rysowania .

W podsumowaniu:

  1. Rasteryzacja - cała zawartość widoku jest rasteryzowana (rysowana lub bufor pikseli poza ekranem) w przestrzeni współrzędnych w granicach widoku. Mogą to być dane obrazu lub niestandardowy rysunek (tj. drawRect:), Ale zawartość widoku podrzędnego. Ta rasteryzacja uwzględnia contentModewłaściwość.

    Wszystko poza granicami widoku jest odrzucane.

  2. Kompozycja - wyniki są zestawiane (narysowane jeden na drugim) z podwidoku do superwizji. Wykorzystuje to właściwość frame widoku podrzędnego.

    Jeśli clipsToBoundswłaściwość znajduje YESsię w superviewie, odrzuca zawartość subview poza jej granice.


2

miał ten sam problem i został rozwiązany przez zaznaczenie opcji „Podglądy klipów”.

Obraz był wyświetlany poprawnie dla wszystkich widoków (3.5,4,4,7,5.5, ipad) w podglądzie scenorysu, ale nie w symulatorze.

Po zaznaczeniu opcji „Podglądy klipów” problem został rozwiązany. :)


1

Sprawdzanie „Podglądy klipów” bezpośrednio w Storyboard / Xib również działało. wprowadź opis obrazu tutaj


0

Moje podwidoki zmieniły rozmiar i zdałem sobie sprawę, że to dlatego, że xib miał ustawiony automatyczny układ: wprowadź opis obrazu tutaj


0

Jeśli wszystko zawiedzie,

wykonaj klipy do granic w metodzie viewDidLayoutSubviews.

Przykład:

  override func viewDidLayoutSubviews() {

    imageProfile.layer.cornerRadius = imageProfile.bounds.size.width/2
    imageProfile.clipsToBounds = true
    imageProfile.layer.masksToBounds = true
 }
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.