UIView вопрос авторотации - PullRequest
0 голосов
/ 27 января 2019

У меня возникают проблемы с автоповоротом UIView, который представляет собой не что иное, как красную линию шириной 4 и высотой, равную половине высоты суперпредставления, в ландшафтном режиме, а в портретном режиме высота составляет 4 точки, а ширина - половина ширины суперпредставления.Вы можете увидеть проблему в GIF.Когда я поворачиваюсь от пейзажа к портрету, эффект автоповорота не плавный и с искажениями.

enter image description here

Вот код.Что я делаю не так?

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 Ответ

0 голосов
/ 27 января 2019

Есть несколько возможных вариантов:

  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()
                }
            })
        })
    }
    

    Существует множество возможных вариантов этой темы.Это по-прежнему оживляет вид, но придает ему более «преднамеренный» вид вибрации и не теряет его «линейного» ощущения.

  2. Вместо анимации frame,Вы можете анимировать transform этого представления, возможно вращая его в направлении, противоположном вращению представления.

  3. Вы можете запустить CADisplayLink во время перехода, изатем обновите кадр так, как вам хочется, в процессе анимации.

...