UIView вопрос авторотации
У меня возникают проблемы с автоповоротом UIView, который представляет собой не что иное, как красную линию шириной 4 и высотой, равную половине высоты суперпредставления, в ландшафтном режиме, а в портретном режиме высота составляет 4 точки, а ширина - половина ширины суперпредставления. Вы можете увидеть проблему в GIF. Когда я поворачиваюсь от пейзажа к портрету, эффект автоповорота не плавный и с искажениями.
Вот код Что я делаю неправильно?
private var myView:UIView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
myView = UIView(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width/2, height: 4))
myView.backgroundColor = UIColor.red
view.addSubview(myView)
myView.center = CGPoint(x: view.bounds.width/2, y: view.bounds.height/2)
}
private func layoutMyView() {
let orientation = UIApplication.shared.statusBarOrientation
if orientation == .landscapeLeft || orientation == .landscapeRight {
myView.frame = CGRect(x: 0, y: 0, width: view.bounds.width/2, height: 4)
} else {
myView.frame = CGRect(x: 0, y: 0, width: 4, height: view.bounds.height/2)
}
myView.center = CGPoint(x: view.bounds.width/2, y: view.bounds.height/2)
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
let orientation = UIApplication.shared.statusBarOrientation
NSLog("View will transition to \(size), \(orientation.rawValue)")
if size.width < size.height {
NSLog("Portrait mode")
} else {
NSLog("Landscape mode")
}
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: { [unowned self] (_) in
let orient = UIApplication.shared.statusBarOrientation
self.layoutMyView()
}, completion: { [unowned self] (UIViewControllerTransitionCoordinatorContext) -> Void in
let orient = UIApplication.shared.statusBarOrientation
self.layoutMyView()
NSLog("rotation completed to \(orient.rawValue), \(self.myView.frame)")
})
}
1 ответ
Есть несколько потенциальных вариантов:
В
animate(alongsideTransition:completion:)
Выполните анимацию по ключевому кадру, чтобы установить среднюю точку анимации, чтобы у вас не возникало странное ощущение квадратной анимации. Например, уменьшите размер до 4х4.override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) let midpointOrigin = CGPoint(x: (view.bounds.midX + view.bounds.midY) / 2 - 2, y: (view.bounds.midX + view.bounds.midY) / 2 - 2) coordinator.animate(alongsideTransition: { _ in UIView.animateKeyframes(withDuration: coordinator.transitionDuration, delay: 0, animations: { UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.5) { self.myView.frame = CGRect(origin: midpointOrigin, size: CGSize(width: 4, height: 4)) } UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.5) { self.layoutMyView() } }) }) }
Есть много возможных вариаций на эту тему. Это по-прежнему оживляет представление, но придает ему более "обдуманный" вид вибрации и не теряет ощущения "линии".
Вместо анимации
frame
Вы могли бы оживитьtransform
этого вида, возможно, вращая его в направлении, противоположном тому, что вид вращается.Вы могли бы запустить
CADisplayLink
пока выполняется переход, а затем обновите кадр до того, что вы хотите в процессе анимации.