для мого UIImageView я вибираю Aspect Fit (InterfaceBuilder), але як я можу змінити вертикальне вирівнювання?
для мого UIImageView я вибираю Aspect Fit (InterfaceBuilder), але як я можу змінити вертикальне вирівнювання?
Відповіді:
[РЕДАКТУВАТИ - цей код трохи запліснявілий з 2011 року, і все, крім я включив моди @ ArtOfWarefare]
Ви не можете зробити це за допомогою UIImageView. Я створив простий підклас UIView, MyImageViewякий містить UIImageView. Код нижче.
// MyImageView.h
#import <UIKit/UIKit.h>
@interface MyImageView : UIView {
UIImageView *_imageView;
}
@property (nonatomic, assign) UIImage *image;
@end
і
// 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
initWithCoder(я в основному скопіювали , initWithFrameале замінив [super initWithFrame:]з [super initWithCoder:]) і 2 - я додав в лінію , if (!self.image) return;щоб layoutSubviewsтаким чином , щоб він не врізатися з неприпустимою геометрією , якщо зображення ISN » t призначається, коли його викликають. З цими двома невеликими змінами це працює надзвичайно.
deallocметод потрібно видалити.
Якщо використовувати Раскадровки, цього можна досягти з обмеженнями ...
Спочатку UIView з бажаним кінцевим кадром / обмеженнями. Додайте UIImageView до UIView. Встановіть для contentMode значення Aspect Fill. Зробіть кадр UIImageView таким самим співвідношенням, як і зображення (це дозволяє уникнути будь-яких попереджень щодо розкадрування пізніше). Закріпіть сторони на UIView, використовуючи стандартні обмеження. Закріпіть верхній АБО нижній (залежно від того, де ви хочете, щоб він був вирівняний) до UIView, використовуючи стандартні обмеження. Нарешті, додайте обмеження пропорції до UIImageView (переконавшись, що це співвідношення як зображення).
Це трохи хитро, оскільки немає можливості встановити подальші правила вирівнювання, якщо ви вже вибрали режим вмісту ( .scaleAspectFit).
Але ось вирішення цього:
Спочатку потрібно явно змінити розмір вихідного зображення, обчисливши розміри (якщо воно було б у UIImageViewз contentMode = .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()
}
}
Тоді вам просто потрібно викликати цю функцію на вихідному зображенні, передавши фрейм imageView і призначити результат вашому UIImageView.imageвластивості. Також переконайтеся, що ви встановили contentModeтут бажаний imageView ( або навіть у Конструкторі інтерфейсів )!
let image = UIImage(named: "MySourceImage")
imageView.image = image?.aspectFitImage(inRect: imageView.frame)
imageView.contentMode = .left
Спробуйте встановити:
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.clipsToBounds = YES;
Це спрацювало для мене.
Я використав UIImageViewAligned для зміни вирівнювання зображення завдяки розробнику
Я знаю, що це стара тема, але я думав поділитися тим, що я зробив, щоб легко змінити обрізану область зверху до низу подання зображень у Interface Builder, на випадок, якщо хтось мав таку ж проблему, як і я. У мене був UIImageView, який заповнював вигляд мого ViewController, і намагався зробити так, щоб верх залишався незмінним, незалежно від розміру екрана пристрою.
Я застосував форм-фактор retina 4 (Editor-> Apply Retina 4 Form Factor).
Я закріпив висоту і ширину.
Тепер, коли екран змінює розмір, UIImageView насправді має однаковий розмір, і контролер перегляду просто відсікає те, що поза екраном. Початок кадру залишається рівним 0,0, тому нижня та права частина зображення обрізані, а не верхня.
Сподіваюся, це допомагає.
Ви можете зробити це, спочатку масштабуючи, а потім змінюючи розмір. Тут слід згадати те, що мене обумовлював зріст. Я маю на увазі, що я мав мати зображення заввишки 34 пікселі і незалежно від того, якою шириною.
Отже, отримайте співвідношення між фактичною висотою вмісту та висотою подання (34 пікселі), а потім масштабуйте також ширину.
Ось як я це зробив:
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];
Сподіваюся, це допомагає.
Я прийшов до такого рішення:
UIImageViewрежим вмісту на top:imageView.contentMode = .topДля завантаження та зміни розміру зображення я використовую Kingfisher :
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)])
Я вирішив це шляхом підкласу UIImageView та заміни методу setImage: Спочатку підклас зберігає вихідні значення для походження та розміру, щоб він міг використовувати початковий розмір набору як обмежувальну рамку.
Я встановив режим вмісту на UIViewContentModeAspectFit. Усередині setImage: я схопив співвідношення ширини та висоти зображення, а потім змінив розмір подання зображення, щоб відповідати такому співвідношенню, як і зображення. Після зміни розміру я відрегулював властивості кадру, щоб встановити вигляд зображення на тому самому місці, що і раніше, а потім зателефонував super setImage :.
Це призводить до перегляду зображення, кадр якого налаштовано відповідно до зображення, тому пристосування сторін працює, і властивості кадру перегляду зображень важко піднімають, розміщуючи вигляд зображення там, де він повинен бути, щоб отримати той самий ефект.
Ось деякий код, який я використовував:
По-перше, і я вважаю це досить корисним загалом, це категорія на UIView, яка полегшує встановлення властивостей кадру у вигляді за допомогою таких властивостей, як лівий, правий, верхній, нижній, ширина, висота тощо.
@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
Це підклас UIImageView. Він не повністю перевірений, але повинен передати ідею. Це можна розширити, щоб встановити власні нові режими вирівнювання.
@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
Якщо вам потрібно домогтися аспекту Fit і позбутися порожніх просторів
Не забудьте видалити обмеження ширини вашого перегляду зображень із розкадрування і насолоджуйтесь
клас 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()
}}
Щоб вирівняти зображення за масштабом, використовуйте автоматичне розміщення. Приклад вирівняного зображення за правою шкалою після масштабування відповідно до UIImageView:
myUIImageView.contentMode = .ScaleAspectFit
myUIImageView.translatesAutoresizingMaskIntoConstraints = false
myUIImageView.image = UIImage(named:"pizza.png")
Масштабоване зображення, що відповідає вашому аспекту, тепер вирівняно в UIImageView
+----------------------------------+
| [IMAGE]|
+----------------------------------+
Змініть обмеження, щоб по-різному вирівняти в режимі перегляду зображення.