iOS自定义过渡和旋转

Tom*_*usX 10 transitions uiviewcontroller ios swift

我正在使用自定义过渡来显示全屏模态游戏视图.当用户启动游戏时,根视图控制器缩小到"进入"屏幕,而全屏游戏视图控制器从较大比例缩放到显示器上,同时从0%不透明度转换到100%不透明度.简单!

过渡看起来很棒并且工作正常,在解雇游戏视图控制器时也正确地反转动画.

我遇到的问题是,如果在显示全屏游戏视图控制器的同时旋转设备,则在返回到根视图控制器时,布局完全是棘手的.并且进一步的旋转不能解决问题,布局是螺旋式的并且保持螺旋状.

如果我禁用自定义转换,这个问题就消失了.此外,如果我保留自定义转换,但禁用在转换动画中的源和目标视图上设置CATransform3D的调用,则问题会再次消失.

这是我的过渡代表:

class FullscreenModalTransitionManager: NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate  {

    private var presenting:Bool = true

    // MARK: UIViewControllerAnimatedTransitioning protocol methods

    func animateTransition(transitionContext: UIViewControllerContextTransitioning) {

        // get reference to our fromView, toView and the container view that we should perform the transition in
        let container = transitionContext.containerView()
        let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)!
        let toView = transitionContext.viewForKey(UITransitionContextToViewKey)!

        let scale:CGFloat = 1.075
        //let bigScale = CGAffineTransformMakeScale(scale, scale)
        //let smallScale = CGAffineTransformMakeScale(1/scale,1/scale)
        let bigScale = CATransform3DMakeScale(scale, scale, 1)
        let smallScale = CATransform3DMakeScale(1/scale, 1/scale, 1)
        let smallOpacity:CGFloat = 0.5
        let presenting = self.presenting

        if presenting {

            // when presenting, incoming view must be on top
            container.addSubview(fromView)
            container.addSubview(toView)

            toView.layer.transform = bigScale
            toView.opaque = false
            toView.alpha = 0

            fromView.layer.transform = CATransform3DIdentity
            fromView.opaque = false
            fromView.alpha = 1
        } else {

            // when !presenting, outgoing view must be on top
            container.addSubview(toView)
            container.addSubview(fromView)

            toView.layer.transform = smallScale
            toView.opaque = false
            toView.alpha = smallOpacity

            fromView.layer.transform = CATransform3DIdentity
            fromView.opaque = false
            fromView.alpha = 1
        }


        let duration = self.transitionDuration(transitionContext)

        UIView.animateWithDuration(duration,
            delay: 0.0,
            usingSpringWithDamping: 0.7,
            initialSpringVelocity: 0,
            options: nil,
            animations: {

                if presenting {
                    fromView.layer.transform = smallScale
                    fromView.alpha = smallOpacity
                } else {
                    fromView.layer.transform = bigScale
                    fromView.alpha = 0
                }

            },
            completion: nil )

        UIView.animateWithDuration(duration,
            delay: duration/6,
            usingSpringWithDamping: 0.7,
            initialSpringVelocity: 0.5,
            options: nil,
            animations: {
                toView.layer.transform = CATransform3DIdentity
                toView.alpha = 1
            },
            completion: { finished in
                transitionContext.completeTransition(true)
            })
    }

    func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval {
        return 0.5
    }

    // MARK: UIViewControllerTransitioningDelegate protocol methods

    func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        self.presenting = true
        return self
    }

    func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        self.presenting = false
        return self
    }
}
Run Code Online (Sandbox Code Playgroud)

而且,对于视觉参考,这是我的根视图控制器通常的样子:

我的根视图控制器的正确布局

而且,对于视觉参考,这里是我的根视图控制器看起来像如果我转动我的设备(至少一次),而在游戏中查看,并返回到根视图控制器.

在全屏游戏视图中旋转设备并返回到根视图后,布局中断

而且最后要说明 - 以防万一它敲响钟声的任何 - 我使用自动布局和大小班奠定了我的根视图控制器.

谢谢,

agi*_*ion 30

我遇到了类似的问题,我在导航控制器上为push和pop编写了一个自定义转换.如果在执行推送后旋转设备,则当您弹回到根视图控制器时,它的框架将保持不变.


问题

在此输入图像描述


目标C.

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {

    // ViewController Reference
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

    // Fix layout bug in iOS 9+
    toViewController.view.frame = [transitionContext finalFrameForViewController:toViewController];

    // The rest of your code ...
} 
Run Code Online (Sandbox Code Playgroud)

Swift 3.0

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

    // ViewController reference
    let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!

    // Fix layout bug in iOS 9+
    toViewController.view.frame = transitionContext.finalFrame(for: toViewController)

    // The rest of your code ...
}
Run Code Online (Sandbox Code Playgroud)


Tom*_*usX 5

我偶然想到这一点,同时在具有非身份转换的视图上做一些手动布局代码.如果您的视图具有非标识转换,则正常布局代码将失败.

我的转换委托中的修复是采用转换视图,并在动画中完成回调设置其转换为标识(因为该视图在动画结束时不可见,并且在新视图后面,这对于外观)

UIView.animateWithDuration(duration,
    delay: 0.0,
    usingSpringWithDamping: 0.7,
    initialSpringVelocity: 0,
    options: nil,
    animations: {

        if presenting {
            fromView.transform = smallScale
            fromView.alpha = smallOpacity
        } else {
            fromView.transform = bigScale
            fromView.alpha = 0
        }

    },
    completion: { completed in
        // set transform of now hidden view to identity to prevent breakage during rotation
        fromView.transform = CGAffineTransformIdentity
    })
Run Code Online (Sandbox Code Playgroud)