viewWillTransitionToSize会导致不旋转的视图控制器重新调整大小和重新定位。

3
许多人讨论了模仿原生iOS相机应用程序的技术(其中UI元素在设备旋转时旋转)。我之前在这里提出了一个问题。大多数人建议锁定UI的方向,然后强制只对要旋转的元素进行变换。这种方法虽然可行,但元素不会像原生iOS应用程序中看到的那样平滑地旋转,而且会引起一些问题。具体来说,我的某些界面允许用户在不离开此界面的情况下分享,但是当共享视图旋转时,它会偏移中心。因此,我想找到一种不同的方式来解决这个问题。
我发现了一个链接到Apple's 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个回答

2

我终于搞定了(虽然花费的时间比预计的多)。我需要设置非旋转视图的宽度和高度参数以在构建时移除,然后在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()方法来实现同样类型的界面(请参阅我的问题)。我认为这种方法是创建这种类型的界面更清晰的方式,但是我还没有能够在运行时不崩溃地使其正常工作。


你好!能不能请你分享一下你创建的视图控制器的代码?我正试图做和你描述的完全一样的东西,而你的方法看起来就是解决方案!我尝试使用你提供的代码,但是我无法将它们组合在一起使其工作。我相信我可以走和你一样的路线,但我确定这需要更多的时间。如果你能分享代码,我会非常感激! - Grigory
经过一系列的实验,终于成功了!感谢您提供的提示。我认为值得一提的是,我们应该将此添加到视图控制器中,以便非旋转视图不会向侧面移动:override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() nonRotatingView.center = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds)) } - Grigory
抱歉回复慢了,不过很高兴你已经解决了问题。 - jreikes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接