Выравнивание UIImageView с Aspect Fit - PullRequest
71 голосов
/ 17 июля 2010

для моего UIImageView Я выбираю Aspect Fit (InterfaceBuilder), но как я могу изменить вертикальное выравнивание?

Ответы [ 11 ]

40 голосов
/ 05 апреля 2011

[РЕДАКТИРОВАТЬ - этот код немного плесень с 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
30 голосов
/ 19 декабря 2014

При использовании раскадровок это может быть достигнуто с ограничениями ...

Во-первых, UIView с желаемым финальным кадром / ограничениями. Добавьте UIImageView в UIView. Установите для contentMode Aspect Fill. Сделайте для кадра UIImageView такое же соотношение, как и для изображения (это позволит избежать любых предупреждений раскадровки позже). Прикрепите стороны к UIView, используя стандартные ограничения. Прикрепите верхний ИЛИ нижний (в зависимости от того, где вы хотите выровнять) к UIView, используя стандартные ограничения. Наконец добавьте ограничение соотношения сторон в UIImageView (убедитесь, что соотношение в качестве изображения).

9 голосов
/ 21 августа 2017

Это немного сложнее, поскольку нет возможности установить дополнительные правила выравнивания, если вы уже выбрали режим содержимого (.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.Кроме того, убедитесь, что вы установили нужный imageView contentMode здесь ( или даже в Интерфейсном Разработчике )!

let image = UIImage(named: "MySourceImage")
imageView.image = image?.aspectFitImage(inRect: imageView.frame)
imageView.contentMode = .left
8 голосов
/ 30 января 2013

Попробуйте установить:

imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.clipsToBounds = YES;

Это сработало для меня.

3 голосов
/ 22 февраля 2016

Я использовал UIImageViewAligned для изменения выравнивания изображения благодаря разработчику

UIImageViewAligned

2 голосов
/ 13 июня 2013

Я знаю, что это старая тема, но я подумала, что поделюсь тем, что я сделал, чтобы легко изменить область обрезки сверху вниз в представлении изображения в Интерфейсном Разработчике, если у кого-то возникла та же проблема, что и я , У меня был UIImageView, который заполнил View моего ViewController, и я пытался сделать верхнюю часть неизменной, независимо от размера экрана устройства.

  1. Я применил форм-фактор Retina 4 (Editor-> Apply Retina 4 Form Factor).

  2. Я закрепил высоту и ширину.

Теперь, когда экран меняет размер, UIImageView на самом деле имеет тот же размер, а контроллер представления просто обрезает то, что находится за пределами экрана. Начало кадра остается равным 0,0, поэтому нижняя и правая части изображения обрезаются, а не верхняя.

Надеюсь, это поможет.

1 голос
/ 04 марта 2019

Я пришел к следующему решению:

  1. Установить UIImageView Режим содержимого на top: imageView.contentMode = .top
  2. Изменить размер изображения в соответствии с границами UIImageView

Для загрузки и изменения размера изображения я использую Зимородок :

let size = imageView.bounds.size
let processor = ResizingImageProcessor(referenceSize: size, mode: .aspectFit)
imageView.kf.setImage(with: URL(string: imageUrl), options: [.processor(processor)])
1 голос
/ 02 октября 2012

Вы можете сделать это сначала с помощью масштабирования, а затем изменения размера.Здесь нужно упомянуть, что я был обусловлен ростом.Я имею в виду, что я должен был иметь изображение высотой 34px и независимо от его ширины.

Итак, получите соотношение между фактической высотой содержимого и высотой представления (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];

Надеюсь, это поможет.

0 голосов
/ 18 апреля 2019

Если вам нужно достигнуть aspectFit и избавиться от пустых мест

Не забудьте убрать ограничение ширины вашего изображения из раскадровки и наслаждайтесь

Класс 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()
}}
0 голосов
/ 12 ноября 2016

Чтобы выровнять масштабируемое изображение по размеру, используйте автоматический макет.Пример выровненного по правому краю изображения после масштабирования по размеру в UIImageView:

  1. Создание UIImageView, содержащего изображение
  2. Добавление автоматических ограничений для правого, верхнего, нижнего, ширины
  3. Установите изображение:
myUIImageView.contentMode = .ScaleAspectFit
myUIImageView.translatesAutoresizingMaskIntoConstraints = false
myUIImageView.image = UIImage(named:"pizza.png")

Ваше масштабированное изображение с форматным соотношением теперь выровнено по правому краю в UIImageView

+----------------------------------+
|                           [IMAGE]|
+----------------------------------+

Измените ограничения для выравнивания по-разномув пределах изображения.

...