dla mojego UIImageView wybieram Aspect Fit (InterfaceBuilder), ale jak mogę zmienić wyrównanie w pionie?
iphone
cocoa-touch
interface-builder
Raegtime
źródło
źródło
Odpowiedzi:
[EDYTUJ - ten kod jest trochę spleśniały, istota z 2011 r. I wszystkie oprócz mnie włączone mody @ ArtOfWarefare]
Nie możesz tego zrobić w / UIImageView. Utworzyłem prostą podklasę UIView,
MyImageView
która zawiera UIImageView. Kod poniżej.// MyImageView.h #import <UIKit/UIKit.h> @interface MyImageView : UIView { UIImageView *_imageView; } @property (nonatomic, assign) UIImage *image; @end
i
// MyImageView.m #import "MyImageView.h" @implementation MyImageView @dynamic image; - (id)initWithCoder:(NSCoder*)coder { self = [super initWithCoder:coder]; if (self) { self.clipsToBounds = YES; _imageView = [[UIImageView alloc] initWithFrame:self.bounds]; _imageView.contentMode = UIViewContentModeScaleAspectFill; [self addSubview:_imageView]; } return self; } - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.clipsToBounds = YES; _imageView = [[UIImageView alloc] initWithFrame:self.bounds]; _imageView.contentMode = UIViewContentModeScaleAspectFill; [self addSubview:_imageView]; } return self; } - (id)initWithImage:(UIImage *)anImage { self = [self initWithFrame:CGRectZero]; if (self) { _imageView.image = anImage; [_imageView sizeToFit]; // initialize frame to be same size as imageView self.frame = _imageView.bounds; } return self; } // Delete this function if you're using ARC - (void)dealloc { [_imageView release]; [super dealloc]; } - (UIImage *)image { return _imageView.image; } - (void)setImage:(UIImage *)anImage { _imageView.image = anImage; [self setNeedsLayout]; } - (void)layoutSubviews { if (!self.image) return; // compute scale factor for imageView CGFloat widthScaleFactor = CGRectGetWidth(self.bounds) / self.image.size.width; CGFloat heightScaleFactor = CGRectGetHeight(self.bounds) / self.image.size.height; CGFloat imageViewXOrigin = 0; CGFloat imageViewYOrigin = 0; CGFloat imageViewWidth; CGFloat imageViewHeight; // if image is narrow and tall, scale to width and align vertically to the top if (widthScaleFactor > heightScaleFactor) { imageViewWidth = self.image.size.width * widthScaleFactor; imageViewHeight = self.image.size.height * widthScaleFactor; } // else if image is wide and short, scale to height and align horizontally centered else { imageViewWidth = self.image.size.width * heightScaleFactor; imageViewHeight = self.image.size.height * heightScaleFactor; imageViewXOrigin = - (imageViewWidth - CGRectGetWidth(self.bounds))/2; } _imageView.frame = CGRectMake(imageViewXOrigin, imageViewYOrigin, imageViewWidth, imageViewHeight); } - (void)setFrame:(CGRect)frame { [super setFrame:frame]; [self setNeedsLayout]; } @end
źródło
initWithCoder
(ja w zasadzie skopiowaniuinitWithFrame
ale otrzymuje[super initWithFrame:]
z[super initWithCoder:]
) i 2 - dodałem w kolejceif (!self.image) return;
dolayoutSubviews
tak, że nie będzie katastrofy z nieprawidłowej geometrii jeżeli ISN obraz” t przypisane, gdy jest wywołane. Z tymi dwoma małymi zmianami działa niesamowicie.dealloc
metoda musi zostać usunięta.Jeśli używasz scenorysów, można to osiągnąć za pomocą ograniczeń ...
Najpierw UIView z żądaną ostateczną klatką / ograniczeniami. Dodaj UIImageView do UIView. Ustaw contentMode na Aspect Fill. Spraw, aby ramka UIImageView miała ten sam współczynnik co obraz (pozwala to uniknąć późniejszych ostrzeżeń Storyboard). Przypnij boki do UIView, używając standardowych wiązań. Przypnij górę LUB dół (w zależności od tego, gdzie chcesz ją wyrównać) do UIView, używając standardowych ograniczeń. Na koniec dodaj ograniczenie współczynnika proporcji do UIImageView (upewniając się, że współczynnik jest taki jak obraz).
źródło
Jest to trochę trudne, ponieważ nie ma opcji ustawiania dalszych reguł wyrównania, jeśli już wybrałeś tryb zawartości (
.scaleAspectFit
).Ale oto obejście tego problemu:
Najpierw musisz jawnie zmienić rozmiar obrazu źródłowego, obliczając wymiary (jeśli byłby w
UIImageView
withcontentMode = .scaleAspectFit
).extension UIImage { func aspectFitImage(inRect rect: CGRect) -> UIImage? { let width = self.size.width let height = self.size.height let aspectWidth = rect.width / width let aspectHeight = rect.height / height let scaleFactor = aspectWidth > aspectHeight ? rect.size.height / height : rect.size.width / width UIGraphicsBeginImageContextWithOptions(CGSize(width: width * scaleFactor, height: height * scaleFactor), false, 0.0) self.draw(in: CGRect(x: 0.0, y: 0.0, width: width * scaleFactor, height: height * scaleFactor)) defer { UIGraphicsEndImageContext() } return UIGraphicsGetImageFromCurrentImageContext() } }
Następnie wystarczy wywołać tę funkcję na oryginalnym obrazie, przekazując ramkę imageView i przypisując wynik do swojej
UIImageView.image
właściwości. Upewnij się również, że ustawiłeścontentMode
tutaj pożądany imageView ( lub nawet w Interface Builder )!let image = UIImage(named: "MySourceImage") imageView.image = image?.aspectFitImage(inRect: imageView.frame) imageView.contentMode = .left
źródło
Spróbuj ustawić:
imageView.contentMode = UIViewContentModeScaleAspectFit; imageView.clipsToBounds = YES;
To zadziałało dla mnie.
źródło
Użyłem UIImageViewAligned do zmiany wyrównania obrazu dzięki deweloperowi
UIImageViewAligned
źródło
Wiem, że to stary wątek, ale pomyślałem, że podzielę się tym, co zrobiłem, aby łatwo zmienić przycięty region z góry na dół widoku obrazu w Interface Builder, na wypadek, gdyby ktoś miał ten sam problem, co ja. Miałem UIImageView, który wypełnił widok mojego ViewController i próbowałem, aby górna część pozostała taka sama, niezależnie od rozmiaru ekranu urządzenia.
Zastosowałem współczynnik kształtu siatkówki 4 (Edytor-> Zastosuj współczynnik kształtu Retina 4).
Przypiąłem wysokość i szerokość.
Teraz, gdy ekran zmienia rozmiar, UIImageView ma w rzeczywistości ten sam rozmiar, a kontroler widoku po prostu przycina to, co jest poza ekranem. Początek ramki pozostaje na 0,0, więc dolna i prawa część obrazu jest przycinana, a nie górna.
Mam nadzieję że to pomoże.
źródło
Możesz to zrobić, najpierw skalując, a następnie zmieniając rozmiar. Warto tutaj wspomnieć, że byłem uwarunkowany wzrostem. Chodzi mi o to, że musiałem mieć obraz o wysokości 34 pikseli i bez względu na szerokość.
Zatem uzyskaj stosunek między rzeczywistą wysokością treści a wysokością widoku (34 piksele), a następnie skaluj również szerokość.
Oto jak to zrobiłem:
CGSize size = [imageView sizeThatFits:imageView.frame.size]; CGSize actualSize; actualSize.height = imageView.frame.size.height; actualSize.width = size.width / (1.0 * (size.height / imageView.frame.size.height)); CGRect frame = imageView.frame; frame.size = actualSize; [imageView setFrame:frame];
Mam nadzieję że to pomoże.
źródło
Doszedłem do następującego rozwiązania:
UIImageView
tryb treści natop
:imageView.contentMode = .top
Aby załadować i zmienić rozmiar obrazu, używam Kingfishera :
let size = imageView.bounds.size let processor = ResizingImageProcessor(referenceSize: size, mode: .aspectFit) imageView.kf.setImage(with: URL(string: imageUrl), options: [.processor(processor), .scaleFactor(UIScreen.main.scale)])
źródło
Rozwiązałem to, podklasując UIImageView i zastępując metodę setImage:. Podklasa najpierw zapisze swoje oryginalne wartości pochodzenia i rozmiaru, aby mogła użyć oryginalnego rozmiaru zestawu jako obwiedni.
Ustawiłem tryb treści na UIViewContentModeAspectFit. Wewnątrz setImage: chwyciłem stosunek szerokości do wysokości obrazu, a następnie zmieniłem rozmiar widoku obrazu, aby dopasować go do tego samego współczynnika co obraz. Po zmianie rozmiaru dostosowałem właściwości klatki, aby ustawić widok obrazu w tym samym miejscu, w którym był wcześniej, a następnie wywołałem super setImage :.
Powoduje to, że widok obrazu, którego ramka jest dopasowana dokładnie do obrazu, działa tak, że dopasowanie proporcji działa, a właściwości ramki widoku obrazu robią duże wrażenie, umieszczając widok obrazu tam, gdzie powinien, aby uzyskać ten sam efekt.
Oto kod, którego użyłem:
Po pierwsze, i ogólnie uważam, że jest to całkiem przydatne, jest kategorią w UIView, która ułatwia ustawianie właściwości ramki w widoku za pomocą właściwości takich jak left, right, top, bottom, width, height itp.
UIImageView + FrameAdditions
@interface UIView (FrameAdditions) @property CGFloat left, right, top, bottom, width, height; @property CGPoint origin; @end @implementation UIView (FrameAdditions) - (CGFloat)left { return self.frame.origin.x; } - (void)setLeft:(CGFloat)left { self.frame = CGRectMake(left, self.frame.origin.y, self.frame.size.width, self.frame.size.height); } - (CGFloat)right { return self.frame.origin.x + self.frame.size.width; } - (void)setRight:(CGFloat)right { self.frame = CGRectMake(right - self.frame.size.width, self.frame.origin.y, self.frame.size.width, self.frame.size.height); } - (CGFloat)top { return self.frame.origin.y; } - (void)setTop:(CGFloat)top { self.frame = CGRectMake(self.frame.origin.x, top, self.frame.size.width, self.frame.size.height); } - (CGFloat)bottom { return self.frame.origin.y + self.frame.size.height; } - (void)setBottom:(CGFloat)bottom { self.frame = CGRectMake(self.frame.origin.x, bottom - self.frame.size.height, self.frame.size.width, self.frame.size.height); } - (CGFloat)width { return self.frame.size.width; } - (void)setWidth:(CGFloat)width { self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, width, self.frame.size.height); } - (CGFloat)height { return self.frame.size.height; } - (void)setHeight:(CGFloat)height { self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, height); } - (CGPoint)origin { return self.frame.origin; } - (void)setOrigin:(CGPoint)origin { self.frame = CGRectMake(origin.x, origin.y, self.frame.size.width, self.frame.size.height); } @end
To jest podklasa UIImageView. Nie jest w pełni przetestowany, ale powinien przekazać pomysł. Można to rozszerzyć, aby ustawić własne nowe tryby wyrównania.
BottomCenteredImageView
@interface BottomCenteredImageView : UIImageView @end @interface BottomCenteredImageView() { CGFloat originalLeft; CGFloat originalBottom; CGFloat originalHeight; CGFloat originalWidth; } @end @implementation BottomCenteredImageView - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if(self) { [self initialize]; } return self; } - (void)awakeFromNib { [self initialize]; } - (void)initialize { originalLeft = self.frame.origin.x; originalHeight = CGRectGetHeight(self.frame); originalWidth = CGRectGetWidth(self.frame); originalBottom = self.frame.origin.y + originalHeight; } - (void)setImage:(UIImage *)image { if(image) { self.width = originalWidth; self.height = originalHeight; self.left = originalLeft; self.bottom = originalBottom; float myWidthToHeightRatio = originalWidth/originalHeight; float imageWidthToHeightRatio = image.size.width/image.size.height; if(myWidthToHeightRatio >= imageWidthToHeightRatio) { // Calculate my new width CGFloat newWidth = self.height * imageWidthToHeightRatio; self.width = newWidth; self.left = originalLeft + (originalWidth - self.width)/2; self.bottom = originalBottom; } else { // Calculate my new height CGFloat newHeight = self.width / imageWidthToHeightRatio; self.height = newHeight; self.bottom = originalBottom; } self.contentMode = UIViewContentModeScaleAspectFit; [super setImage:image]; } else { [super setImage:image]; } } @end
źródło
Jeśli chcesz osiągnąć aspekt, dopasuj i pozbądź się pustych przestrzeni
Nie zapomnij usunąć ograniczenia szerokości widoku obrazu ze scenorysu i ciesz się
class SelfSizedImageView: UIImageView {
override func layoutSubviews() { super.layoutSubviews() guard let imageSize = image?.size else { return } let viewBounds = bounds let imageFactor = imageSize.width / imageSize.height let newWidth = viewBounds.height * imageFactor let myWidthConstraint = self.constraints.first(where: { $0.firstAttribute == .width }) myWidthConstraint?.constant = min(newWidth, UIScreen.main.bounds.width / 3) layoutIfNeeded() }}
źródło
Aby wyrównać obraz w celu dopasowania, użyj układu automatycznego. Przykładowy obraz wyrównany do prawej po skalowaniu do dopasowania w UIImageView:
Twój skalowany obraz z dopasowaniem proporcji jest teraz wyrównany do prawej w UIImageView
+----------------------------------+ | [IMAGE]| +----------------------------------+
Zmień ograniczenia, aby wyrównać je inaczej w widoku obrazu.
źródło