UIViewControllerAnimatedTransitioning:旋转改变后的黑屏碎片 [英] UIViewControllerAnimatedTransitioning: Black screen fragments after rotation change

查看:27
本文介绍了UIViewControllerAnimatedTransitioning:旋转改变后的黑屏碎片的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经创建了一个 Viewcontrollertransition,只要我不改变设备方向,一切都会正常工作.

I have created a Viewcontrollertransition and everything is working as long as I don't change the device orientation.

图 1 显示了屏幕应有的样子.然后我切换到下一个视图控制器,在那里我改变方向.现在我回到第一个视图控制器并再次切换方向.然后我在图像 2 中看到结果.出现黑色边框.请不要介意屏幕中央的白框.

Image 1 shows the screen as it should be. I then switch to the next viewcontroller where I change the orientation. Now I go back to first viewcontroller and again switch the orientation. Then I get the result visible in image 2. A black border appears. Please don't mind the white box in the center of the screen.

下面是我的动画代码.你能看出哪里出了问题吗?

Below you find the code of my animation. Can you see what is wrong?

import Foundation

import UIKit

class ZoomOutCircleViewTransition: NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate {

    var hideDelayed = false
    var transitionContext: UIViewControllerContextTransitioning?

    init(hideDelayed : Bool = true) {
        self.hideDelayed = hideDelayed
        super.init()
    }


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

    func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
        self.transitionContext = transitionContext

        guard let toViewController: UIViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) else {
            return
        }

        guard let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) else {
            return
        }

        guard let toViewTransitionFromView = toViewController as? TransitionFromViewProtocol else {
            return
        }

        let containerView = transitionContext.containerView()

        let imageViewSnapshot = toViewTransitionFromView.getViewForTransition()
        imageViewSnapshot.alpha = 0.0
        let imageViewSnapshotOriginalFrame = imageViewSnapshot.frame

        let startFrame = CGRectMake(-CGRectGetWidth(toViewController.view.frame)/2, -CGRectGetHeight(toViewController.view.frame)/2, CGRectGetWidth(toViewController.view.frame)*2, CGRectGetHeight(toViewController.view.frame)*2)

        let quadraticStartFrame = CGRect(x: startFrame.origin.x - (startFrame.height - startFrame.width)/2, y: startFrame.origin.y, width: startFrame.height, height: startFrame.height)

        containerView!.insertSubview(toViewController.view, atIndex: 0)
        containerView!.addSubview(imageViewSnapshot)


        // UIViewController circle shrink animation
        let bigCirclePath = UIBezierPath(ovalInRect: quadraticStartFrame)

        let smallCirclePath = UIBezierPath(ovalInRect: imageViewSnapshot.frame)
        let maskLayer = CAShapeLayer()
        maskLayer.frame = toViewController.view.frame
        maskLayer.path = bigCirclePath.CGPath//maskPath.CGPath
        fromViewController.view.layer.mask = maskLayer

        let pathAnimation = CABasicAnimation(keyPath: "path")
        pathAnimation.delegate = self
        pathAnimation.fromValue = bigCirclePath.CGPath
        pathAnimation.toValue = smallCirclePath.CGPath
        pathAnimation.duration = transitionDuration(transitionContext)
        maskLayer.path = smallCirclePath.CGPath
        maskLayer.addAnimation(pathAnimation, forKey: "pathAnimation")

        //        pathAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)

        imageViewSnapshot.frame = quadraticStartFrame

        // Make imageView visible with animation
        let showImageViewAnimation =  {
            imageViewSnapshot.alpha = 1.0
        }
        let showImageViewDelay = 0.3
        UIView.animateWithDuration(transitionDuration(transitionContext) - showImageViewDelay , delay: showImageViewDelay, options: UIViewAnimationOptions.CurveLinear, animations: showImageViewAnimation) { (completed) -> Void in
        }

        // Shrink the imageView to the original size
        let scaleImageViewAnimation = {
            imageViewSnapshot.frame = imageViewSnapshotOriginalFrame
        }
        UIView.animateWithDuration(transitionDuration(transitionContext), delay: 0.0, options: UIViewAnimationOptions.CurveLinear, animations: scaleImageViewAnimation) { (completed) -> Void in
            // After the complete animations have endet

            // Hide ImageView after it is completely resized. Added some animation delay to not abruptly change the contactImage
            if self.hideDelayed {
                let hideImageViewAnimation =  {
                    imageViewSnapshot.alpha = 0.0
                }
                UIView.animateWithDuration(0.2 , delay: 0.2, options: UIViewAnimationOptions.CurveLinear, animations: hideImageViewAnimation) { (completed) -> Void in
                    imageViewSnapshot.removeFromSuperview()
                }
            }
            else {
                imageViewSnapshot.removeFromSuperview()
            }
        }
    }

    override func animationDidStop(anim: CAAnimation, finished flag: Bool) {
        if let transitionContext = self.transitionContext {
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
        }
    }

    // MARK: UIViewControllerTransitioningDelegate protocol methods

    // return the animataor when presenting a viewcontroller
    func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return self
    }

    // return the animator used when dismissing from a viewcontroller
    func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return self
    }

}

推荐答案

您需要将新框架设置为 toViewController.view.这会将视图更新为当前方向.

You need set new frame to toViewController.view. This will update the view to current orientation.

toViewController.view.frame = fromViewController.view.frame

使用我更新的代码:

class ZoomOutCircleViewTransition: NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate {

    var hideDelayed = false
    var transitionContext: UIViewControllerContextTransitioning?

    init(hideDelayed : Bool = true) {
        self.hideDelayed = hideDelayed
        super.init()
    }


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

    func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
        self.transitionContext = transitionContext

        guard let toViewController: UIViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) else {
            return
        }

        guard let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) else {
            return
        }

        guard let toViewTransitionFromView = toViewController as? TransitionFromViewProtocol else {
            return
        }

        toViewController.view.frame = fromViewController.view.frame

        let containerView = transitionContext.containerView()

        let imageViewSnapshot = toViewTransitionFromView.getViewForTransition()
        imageViewSnapshot.alpha = 0.0
        let imageViewSnapshotOriginalFrame = imageViewSnapshot.frame

        let startFrame = CGRectMake(-CGRectGetWidth(fromViewController.view.frame)/2, -CGRectGetHeight(fromViewController.view.frame)/2, CGRectGetWidth(toViewController.view.frame)*2, CGRectGetHeight(toViewController.view.frame)*2)

        let quadraticStartFrame = CGRect(x: startFrame.origin.x - (startFrame.height - startFrame.width)/2, y: startFrame.origin.y, width: startFrame.height, height: startFrame.height)

        containerView!.insertSubview(toViewController.view, atIndex: 0)
        containerView!.addSubview(imageViewSnapshot)


        // UIViewController circle shrink animation
        let bigCirclePath = UIBezierPath(ovalInRect: quadraticStartFrame)

        let smallCirclePath = UIBezierPath(ovalInRect: imageViewSnapshot.frame)
        let maskLayer = CAShapeLayer()
        maskLayer.frame = toViewController.view.frame
        maskLayer.path = bigCirclePath.CGPath//maskPath.CGPath
        fromViewController.view.layer.mask = maskLayer

        let pathAnimation = CABasicAnimation(keyPath: "path")
        pathAnimation.delegate = self
        pathAnimation.fromValue = bigCirclePath.CGPath
        pathAnimation.toValue = smallCirclePath.CGPath
        pathAnimation.duration = transitionDuration(transitionContext)
        maskLayer.path = smallCirclePath.CGPath
        maskLayer.addAnimation(pathAnimation, forKey: "pathAnimation")

        //        pathAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)

        imageViewSnapshot.frame = quadraticStartFrame

        // Make imageView visible with animation
        let showImageViewAnimation =  {
            imageViewSnapshot.alpha = 1.0
        }
        let showImageViewDelay = 0.3
        UIView.animateWithDuration(transitionDuration(transitionContext) - showImageViewDelay , delay: showImageViewDelay, options: UIViewAnimationOptions.CurveLinear, animations: showImageViewAnimation) { (completed) -> Void in
        }

        // Shrink the imageView to the original size
        let scaleImageViewAnimation = {
            imageViewSnapshot.frame = imageViewSnapshotOriginalFrame
        }
        UIView.animateWithDuration(transitionDuration(transitionContext), delay: 0.0, options: UIViewAnimationOptions.CurveLinear, animations: scaleImageViewAnimation) { (completed) -> Void in
            // After the complete animations have endet

            // Hide ImageView after it is completely resized. Added some animation delay to not abruptly change the contactImage
            if self.hideDelayed {
                let hideImageViewAnimation =  {
                    imageViewSnapshot.alpha = 0.0
                }
                UIView.animateWithDuration(0.2 , delay: 0.2, options: UIViewAnimationOptions.CurveLinear, animations: hideImageViewAnimation) { (completed) -> Void in
                    imageViewSnapshot.removeFromSuperview()
                }
            }
            else {
                imageViewSnapshot.removeFromSuperview()
            }
            toViewController.view.layer.mask = nil
        }
    }

    override func animationDidStop(anim: CAAnimation, finished flag: Bool) {
        if let transitionContext = self.transitionContext {
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
        }
    }

    // MARK: UIViewControllerTransitioningDelegate protocol methods

    // return the animataor when presenting a viewcontroller
    func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return self
    }

    // return the animator used when dismissing from a viewcontroller
    func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return self
    }

}

class ZoomOutCircleViewTransition: NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate {

    var hideDelayed = false
    var transitionContext: UIViewControllerContextTransitioning?

    init(hideDelayed : Bool = true) {
        self.hideDelayed = hideDelayed
        super.init()
    }


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

    func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
        self.transitionContext = transitionContext

        guard let toViewController: UIViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) else {
            return
        }

        guard let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) else {
            return
        }

        guard let toViewTransitionFromView = toViewController as? TransitionFromViewProtocol else {
            return
        }

        toViewController.view.frame = fromViewController.view.frame

        let containerView = transitionContext.containerView()

        let imageViewSnapshot = toViewTransitionFromView.getViewForTransition()
        imageViewSnapshot.alpha = 0.0
        let imageViewSnapshotOriginalFrame = imageViewSnapshot.frame

        let startFrame = CGRectMake(-CGRectGetWidth(fromViewController.view.frame)/2, -CGRectGetHeight(fromViewController.view.frame)/2, CGRectGetWidth(toViewController.view.frame)*2, CGRectGetHeight(toViewController.view.frame)*2)

        let quadraticStartFrame = CGRect(x: startFrame.origin.x - (startFrame.height - startFrame.width)/2, y: startFrame.origin.y, width: startFrame.height, height: startFrame.height)

        containerView!.insertSubview(toViewController.view, atIndex: 0)
        containerView!.addSubview(imageViewSnapshot)


        // UIViewController circle shrink animation
        let bigCirclePath = UIBezierPath(ovalInRect: quadraticStartFrame)

        let smallCirclePath = UIBezierPath(ovalInRect: imageViewSnapshot.frame)
        let maskLayer = CAShapeLayer()
        maskLayer.frame = toViewController.view.frame
        maskLayer.path = bigCirclePath.CGPath//maskPath.CGPath
        fromViewController.view.layer.mask = maskLayer

        let pathAnimation = CABasicAnimation(keyPath: "path")
        pathAnimation.delegate = self
        pathAnimation.fromValue = bigCirclePath.CGPath
        pathAnimation.toValue = smallCirclePath.CGPath
        pathAnimation.duration = transitionDuration(transitionContext)
        maskLayer.path = smallCirclePath.CGPath
        maskLayer.addAnimation(pathAnimation, forKey: "pathAnimation")

        //        pathAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)

        imageViewSnapshot.frame = quadraticStartFrame

        // Make imageView visible with animation
        let showImageViewAnimation =  {
            imageViewSnapshot.alpha = 1.0
        }
        let showImageViewDelay = 0.3
        UIView.animateWithDuration(transitionDuration(transitionContext) - showImageViewDelay , delay: showImageViewDelay, options: UIViewAnimationOptions.CurveLinear, animations: showImageViewAnimation) { (completed) -> Void in
        }

        // Shrink the imageView to the original size
        let scaleImageViewAnimation = {
            imageViewSnapshot.frame = imageViewSnapshotOriginalFrame
        }
        UIView.animateWithDuration(transitionDuration(transitionContext), delay: 0.0, options: UIViewAnimationOptions.CurveLinear, animations: scaleImageViewAnimation) { (completed) -> Void in
            // After the complete animations have endet

            // Hide ImageView after it is completely resized. Added some animation delay to not abruptly change the contactImage
            if self.hideDelayed {
                let hideImageViewAnimation =  {
                    imageViewSnapshot.alpha = 0.0
                }
                UIView.animateWithDuration(0.2 , delay: 0.2, options: UIViewAnimationOptions.CurveLinear, animations: hideImageViewAnimation) { (completed) -> Void in
                    imageViewSnapshot.removeFromSuperview()
                }
            }
            else {
                imageViewSnapshot.removeFromSuperview()
            }
            toViewController.view.layer.mask = nil
        }
    }

    override func animationDidStop(anim: CAAnimation, finished flag: Bool) {
        if let transitionContext = self.transitionContext {
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
        }
    }

    // MARK: UIViewControllerTransitioningDelegate protocol methods

    // return the animataor when presenting a viewcontroller
    func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return self
    }

    // return the animator used when dismissing from a viewcontroller
    func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return self
    }
}

这篇关于UIViewControllerAnimatedTransitioning:旋转改变后的黑屏碎片的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆