UIImageView/UIScrollView заставляет фиксированное соотношение сторон соответствовать экрану

Я делаю простое приложение для iPad, которое состоит из гигантского изображения, которое вы можете масштабировать/выходить и перемещаться.

Это изображение помещается внутри UIImageView, которое затем помещается внутри UIScrollView.

Навигация и масштабирование работают на 100% штрафа; однако изображение загружается с фиксированным соотношением сторон для соответствия экрану и никогда не будет меняться (даже при масштабировании).

У меня такое чувство, что Interface Builder устанавливает какое-то свойство, о котором я не знаю, но я пробовал все, что я могу придумать, чтобы исправить это.

Проблема:

Когда приложение изначально загружается, содержимое внутри UIScrollView автоматически изменяется, чтобы точно соответствовать экрану iPad, изменив его соотношение сторон. /fixed; фактическое изображение является гигантским (путь больше, чем разрешение iPad). Это масштабированное соотношение сторон сохраняется даже при масштабировании изображения и вызывает растяжение изображения.

Независимо от того, что я пытаюсь, я не могу остановить iPad от автоматического масштабирования моего изображения. Я просто хочу, чтобы приложение начинало с моего изображения, отображаемого нормально (100% масштабирование) на iPad, причем часть, которая в настоящее время подходит на экране iPad, является левым верхним углом изображения.

Что я пытался исправить:

Я попытался изменить режим содержимого UIImageView's в Interface Builder на "Top-Left". Казалось, что это работает отлично, но потом я понял, что UIScrollView не позволит вам прокручивать изображение мимо первоначально отображаемой части (вверху слева). Вы можете увеличивать масштаб в верхней левой части и прокручивать, но никогда не проходите мимо того, что первоначально было показано на экране.

Код:

Вот код, который я использую для настройки представлений. imageScrollView - это UIScrollView, а imageView - UIImageView. Они оба IBOutlets.

   // Set the needed attributes of the imageView
    [imageView setImage:[UIImage imageNamed: @"TestImage.png"]];
    imageView.userInteractionEnabled = YES;

    // Set a bunch of the imageScrollView attributes.

    // calculate minimum scale to perfectly fit image width, and begin at that scale
    float minimumScale = [imageScrollView frame].size.width  / [imageView frame].size.width;
    [imageScrollView setMinimumZoomScale:minimumScale];
    [imageScrollView setZoomScale:1];
    [imageScrollView setMaximumZoomScale:10];
    [imageScrollView setContentSize:CGSizeMake(imageView.frame.size.width, imageView.frame.size.height)];
    [imageScrollView setScrollEnabled:YES];
    [imageScrollView setUserInteractionEnabled:YES];
    imageScrollView.clipsToBounds = YES;
    imageScrollView.bounces = FALSE;
    imageScrollView.bouncesZoom = FALSE;

У меня также есть два UIGestureRecongizers для обработки крана, но я не думаю, что это проблема. Когда я их прокомментирую, ничего не меняется.

Любая помощь будет чрезвычайно оценена.

Ответ 1

Я исправил это!

Для тех, у кого есть такая же проблема, вот как я исправил код:

Причина ошибки заключалась в том, что Interface Builder заставлял представления использовать ScaleToFill contentMode. Установка ScrollView's contentMode на UIViewContentModeScaleAspectFit не работала сама по себе, так как imageView все еще искажалась.

Исправление:

Следующий код должен был быть добавлен в конце настройки для UIScrollView и UIImageView (внутри метода viewDidLoad()):

    [imageScrollView setContentMode:UIViewContentModeScaleAspectFit];
    [imageView sizeToFit];
    [imageScrollView setContentSize:CGSizeMake(imageView.frame.size.width, imageView.frame.size.height)];

Объяснение:

Во-первых, UIScrollView's contentMode установлен на AspectFit, как предположил @Mike. Затем sizeToFit() вызывается в imageView, чтобы переопределить предварительные настройки интерфейса Builder и сделать изображение правильным.

Последняя строка важна. Вы должны установить contentSize для ScrollView ПОСЛЕ того, как вы измените размер imageView. В противном случае ScrollView будет думать, что изображение по-прежнему является размером экрана iPad, и поэтому не будет думать, что там что-то прокручивается. Установка размера ScrollView после изменения размера imageView и изменения ScrollView's contentMode делает ScrollView фактический размер изображения.

Надеюсь, что это помогло!

Спасибо за помощь Майку, это привело меня на правильный путь:)

  • Alex

Ответ 2

Поскольку imageView - это содержимое прокрутки, попробуйте изменить режим содержимого ScrollView's на UIViewContentModeScaleAspectFit. Попробуйте вызвать setNeedsDisplay на imageView.

Ответ 3

Для тех, кто пытается исправить изображение в ландшафтном режиме, используя UICollectionView, когда изображение должно быть полноэкранным.

В вашем - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath выполните следующие действия:

CGFloat newWidth = self.view.bounds.size.width; //if iPad in landscape and fullscreen value is 1024
CGFloat newHeight = image.size.height / image.size.width * newWidth;

cell.clipsToBounds = YES;
cell.imageView.frame = CGRectMake(0, 0, newWidth, newHeight);
cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
cell.imageView.image = image;
cell.scrollView.contentSize = cell.imageView.frame.size;

Ключевое значение заключается в том, чтобы обеспечить правильное соотношение размеров изображения при сохранении правильного соотношения сторон.

Ответ 4

Этот код работал у меня: (Swift)

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    let imgView = UIImageView(image: UIImage(named: "MyImage"))
    imgView.contentMode = .ScaleAspectFit
    var size = imgView.frame.size
    size.height = size.height / size.width * scrollView.frame.width
    size.width = scrollView.frame.width
    imgView.frame.size = size
    scrollView.addSubview(imgView)
    scrollView.contentSize = size
}