viewWillTransitionToSize заставляет невращающийся контроллер представления изменять размеры и перемещать
Многие люди обсуждали методы для имитации собственного приложения камеры iOS (где элементы пользовательского интерфейса поворачиваются на месте при вращении устройства). Я на самом деле задал вопрос об этом раньше здесь. У большинства людей вы блокируете ориентацию пользовательского интерфейса, но затем навязываете преобразование только тех элементов, которые вы хотите изменить. Это работает, но элементы не вращаются с плавной анимацией, которую вы видите в родном приложении iOS, и это приводит к некоторым проблемам. В частности, часть моего интерфейса позволяет пользователям обмениваться информацией, не выходя из этого интерфейса, но когда вид совместного использования поворачивается, он выходит за пределы центра. Поэтому я хотел найти другой способ сделать это.
Я нашел ссылку на образец Apple AVCam, который положил мне начало здесь. Я новичок в этом, но мне уже удалось преобразовать его из Obj-C в Swift. Ниже приведен ключевой элемент того, что я сейчас использую:
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
coordinator.animateAlongsideTransition({ (UIViewControllerTransitionCoordinatorContext) -> Void in
//Code here performs animations during the rotation
let deltaTransform: CGAffineTransform = coordinator.targetTransform()
let deltaAngle: CGFloat = atan2(deltaTransform.b, deltaTransform.a)
var currentRotation: CGFloat = self.nonRotatingView.layer.valueForKeyPath("transform.rotation.z") as! CGFloat
// Adding a small value to the rotation angle forces the animation to occur in a the desired direction, preventing an issue where the view would appear to rotate 2PI radians during a rotation from LandscapeRight -> LandscapeLeft.
currentRotation += -1 * deltaAngle + 0.0001;
self.nonRotatingView.layer.setValue(currentRotation, forKeyPath: "transform.rotation.z")
}, completion: { (UIViewControllerTransitionCoordinatorContext) -> Void in
print("rotation completed");
// Code here will execute after the rotation has finished
// Integralize the transform to undo the extra 0.0001 added to the rotation angle.
var currentTransform: CGAffineTransform = self.nonRotatingView.transform
currentTransform.a = round(currentTransform.a)
currentTransform.b = round(currentTransform.b)
currentTransform.c = round(currentTransform.c)
currentTransform.d = round(currentTransform.d)
self.nonRotatingView.transform = currentTransform
})
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
}
Затем у меня есть отдельные контроллеры представления для значков, которые выполняют те же преобразования в противоположном направлении. Значки теперь действительно правильно поворачиваются (с плавной анимацией и прочим), а предварительный просмотр камеры остается правильно ориентированным.
Проблема в том, что размер невращающегося изображения изменяется, и все становится неуместным, когда я поворачиваю устройство из портретной в альбомную или наоборот. Как мне это исправить?
1 ответ
Я получил это работает (хотя это заняло у меня гораздо больше времени, чем следовало бы). Мне нужно было установить параметры ширины и высоты для невращающегося представления, чтобы удалить его во время сборки, а затем добавить следующее к viewDidLoad():
let nonRotatingWidth = nonRotatingView.widthAnchor.constraintEqualToConstant(UIScreen.mainScreen().bounds.width)
let nonRotatingHeight = nonRotatingView.heightAnchor.constraintEqualToConstant(UIScreen.mainScreen().bounds.height)
nonRotatingView.addConstraints([nonRotatingWidth, nonRotatingHeight])
При этом используется новый синтаксис ограничений Swift 2, который относительно лаконичен и удобен для чтения.
Я также возился только с использованием нового синтаксиса ограничений (и без преобразований) для достижения того же типа интерфейса через updateViewConstraints() (см. Мой вопрос об этом здесь). Я считаю, что такой подход является более чистым способом создания интерфейса такого типа, но я пока не смог заставить его работать без сбоев во время выполнения.