Проблема изменения размера UIImageView в UIPageViewController

Я создаю новое приложение и хочу начать "приветственное пошаговое руководство" в начале, когда у меня есть раскадровка с серией изображений, представленных в UIPageViewController. Я загружаю изображения и все это прекрасно, однако изображения изменяются каждый раз, когда они выходят за рамки "предыдущего" или "следующего" ViewController. Я использую Swift для разработки.

Вот видеоролик проблемы: http://youtu.be/dXcjjT-8Bk0

Я пробовал все различные режимы просмотра (Aspect fit, aspect fill, redraw и т.д.), и все они ведут себя одинаково.

Я использую классы Auto-Layout + Size, так как хочу упростить разработку для разных размеров экрана. Текущие ограничения, которые у меня есть, делают UIImage видимыми в правильном размере:

Align Centre X  to Superview
Top Space to Top Layout Guide
Bottom Space to Bottom Layout Guide + Equals: 50

В настоящее время я использую Aspect Fit, который дает мне правильное изображение (после того, как они выполнили свое "изменение размера".

Может ли кто-нибудь объяснить мне, как это исправить?

Ответ 1

Из вашего видео я заметил, что ваш UIImageView всегда "изменен" сверху, а не внизу. Это, безусловно, связано с вашим ограничением автоопределения, которое вы называете "Top Space to Top Layout Guide". Пока ваш контроллер просмотра UIImageView переходит через ваш контроллер просмотра прокрутки, он не знает, где находится верхний макет, поэтому его topLayoutGuide.length - 0. Только после завершения анимации контроллер представления получает положительное значение для topLayoutGuide.length. Да, контроллер просмотра страницы должен быть немного умнее этого, но это не так. Вы можете либо прекратить использование верхнего руководства по макете, либо сделать ограничение автоопределения относительно верхней части своего супервизора. Или вы можете продолжать использовать верхний макет, но учитываете, когда он length равен 0. Вы можете сделать это, создав выход для своего раскадровки NSLayoutConstraint и переопределив viewWillLayoutSubviews() в ViewController, содержащий ваш UIImageView s:

@IBOutlet weak var topSpaceToTLG: NSLayoutConstraint!
var parentTLGlength: CGFloat = 20

override func viewWillLayoutSubviews() {
    if self.topLayoutGuide.length == 0 {
        // Lengthen the autolayout constraint to where we know the 
        // top layout guide will be when the transition completes
        topSpaceToTLG.constant = parentTLGlength
    } else {
        topSpaceToTLG.constant = 0
    }
}

Это всегда будет помещать верхнюю часть вашего UIImageView в верхнюю направляющую макета, предполагая, что строка состояния всегда 20 точек. Перед тем, как выложить подзаголовки, он проверяет, соответствует ли длина верхнего макета 0 или нет, и соответственно настраивает ограничение автоопределения. После завершения анимации перехода макет снова запускается, а верхняя длина направляющей макета будет ожидаемой, поэтому константа ограничения может вернуться к 0. Даже лучше, чем hardcoding, значение заключается в том, чтобы передавать в родительском представлении точную длину контроллера во время инициализации, учитывая любые возможные изменения в руководстве по началу работы, например, добавление навигационной панели.

Ответ 2

Из видео, которое, я думаю, вы могли бы решить это, предотвратив расширение UIPageViewController под верхними барами.

В xcode вы можете сделать это, используя инспектор атрибутов для контроллера просмотра страницы, сняв флажок "Расширять края в верхних барах".

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

Ответ 3

Я понял, что проблема заключается в том, что когда диспетчер представлений начал анимировать верхние и нижние макеты, гиды не имели высоты. Правый и левый поля тоже не были. Когда представление закончило анимацию, все они получили высоту или ширину, и мой вид изменил размер. Я исправил эту проблему в своем проекте, добавив вертикальные ограничения между моими объектами и их супер-представлением, а не в Руководство по макету Top/Bottom. Я также должен был изменить свои горизонтальные ограничения, чтобы игнорировать боковые поля.

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