UIView 分割过渡

fuz*_*oat 2 transition uiviewcontroller uiview uiviewanimationtransition ios

很有可能我只是为此使用了错误的术语,但我一直在寻找是否有 iOS UIView 转换可以拆分视图 (BLUE) 和任何子视图控件以显示另一个视图 (RED) 及其控件。我发现有几篇帖子提到了 2011 年的类似内容,但最近都没有,所以想知道现在是否添加了任何新内容,我们已经升级到 iOS 8。任何指针都将不胜感激。

在此处输入图片说明

San*_*eep 5

如果您正在尝试进行这种拆分过渡,我已经为视图控制器过渡创建了一个动画控制器。如果查看代码,您会发现可以有两种不同的传输方式,从视图中间打开或从视图顶部折叠。

这是下面代码如何工作的一个小gif;

在此处输入图片说明

class AnimationController: NSObject, UIViewControllerAnimatedTransitioning {

    let presenting: Bool

    init(presenting: Bool) {
        self.presenting = presenting
    }

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

    func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
         animateOutImagesWithContext(transitionContext)
        //animateInImagesWithContext(transitionContext)
    }

    func snapshotView(view: UIView!) -> UIImage {
        UIGraphicsBeginImageContext(view.bounds.size)
        view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
        let snapshotImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return snapshotImage
    }

    func animateOutImagesWithContext(transitionContext:UIViewControllerContextTransitioning) {

        let containerView = transitionContext.containerView()

        let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
        let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)

        let fromView = fromViewController!.view
        let toView = toViewController!.view

        containerView.addSubview(toView)

        let snapshotImage = snapshotView(fromView)

        fromView.removeFromSuperview()

        let imageViews = animatingOutImageViews(snapshotImage)

        containerView.addSubview(imageViews.firstImageView)
        containerView.addSubview(imageViews.secondImageView)

      UIView.animateWithDuration(transitionDuration(transitionContext), animations: { () -> Void in
            let firstImageView = imageViews.firstImageView
            let secondImageView = imageViews.secondImageView

            if self.presenting {

                firstImageView.frame = CGRectOffset(firstImageView.frame, -CGRectGetWidth(firstImageView.frame), 0)
                secondImageView.frame = CGRectOffset(secondImageView.frame, CGRectGetWidth(secondImageView.frame), 0)                 
            } else {
                firstImageView.frame = CGRectOffset(firstImageView.frame, 0, -CGRectGetHeight(firstImageView.frame))
                secondImageView.frame = CGRectOffset(secondImageView.frame, 0, CGRectGetHeight(secondImageView.frame))

            }
            }) { (completed: Bool) -> Void in
                imageViews.firstImageView.removeFromSuperview()
                imageViews.secondImageView.removeFromSuperview()
            transitionContext.completeTransition(true)
        }

    }

    func animateInImagesWithContext(transitionContext:UIViewControllerContextTransitioning) {
        let containerView = transitionContext.containerView()

        let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
        let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)

        let fromView = fromViewController!.view
        let toView = toViewController!.view

        containerView.insertSubview(toView, belowSubview: fromView)

        let snapshotImage = snapshotView(toView)

        let imageViews = animatingInImageViews(snapshotImage)

        containerView.addSubview(imageViews.firstImageView)
        containerView.addSubview(imageViews.secondImageView)

      UIView.animateWithDuration(transitionDuration(transitionContext), animations: { () -> Void in
            let firstImageView = imageViews.firstImageView
            let secondImageView = imageViews.secondImageView

            if self.presenting {

                firstImageView.frame = CGRectOffset(firstImageView.frame, 0, CGRectGetHeight(firstImageView.frame))
                secondImageView.frame = CGRectOffset(secondImageView.frame, 0, -CGRectGetHeight(secondImageView.frame))

            } else {
                firstImageView.frame = CGRectOffset(firstImageView.frame, CGRectGetWidth(firstImageView.frame), 0)
                secondImageView.frame = CGRectOffset(secondImageView.frame, -CGRectGetWidth(secondImageView.frame),0)

            }
            }) { (completed: Bool) -> Void in
                fromView.removeFromSuperview()
                imageViews.firstImageView.removeFromSuperview()
                imageViews.secondImageView.removeFromSuperview()
                transitionContext.completeTransition(true)
        }           
    }

    func animatingOutImageViews(snapshotImage: UIImage)  -> (firstImageView: UIImageView!, secondImageView: UIImageView!)
    {
        let imageSize = snapshotImage.size

        var firstPartFrame: CGRect
        var secondPartFrame: CGRect

        if presenting {
            firstPartFrame = CGRectMake(0, 0, imageSize.width * 0.5, imageSize.height)
            secondPartFrame = CGRectOffset(firstPartFrame, CGRectGetWidth(firstPartFrame), 0)
        } else {
            firstPartFrame = CGRectMake(0, 0, imageSize.width, imageSize.height * 0.5)
            secondPartFrame = CGRectOffset(firstPartFrame, 0, CGRectGetHeight(firstPartFrame))
        }

        let firstImage = getImage(snapshotImage, insideRect: firstPartFrame)
        let secondImage = getImage(snapshotImage, insideRect: secondPartFrame)

        let firstImageView = UIImageView(frame: firstPartFrame)
        firstImageView.image = firstImage
        let secondImageView = UIImageView(frame: secondPartFrame)
        secondImageView.image = secondImage

        return (firstImageView, secondImageView)
    }

    func animatingInImageViews(snapshotImage: UIImage)  -> (firstImageView: UIImageView!, secondImageView: UIImageView!)
    {
        let imageSize = snapshotImage.size

        var firstPartFrame: CGRect
        var secondPartFrame: CGRect

        if presenting {
            firstPartFrame = CGRectMake(0, 0, imageSize.width, imageSize.height * 0.5)
            secondPartFrame = CGRectOffset(firstPartFrame, 0, CGRectGetHeight(firstPartFrame))
        } else {
            firstPartFrame = CGRectMake(0, 0, imageSize.width * 0.5, imageSize.height)
            secondPartFrame = CGRectOffset(firstPartFrame, CGRectGetWidth(firstPartFrame), 0)
        }

        let firstImage = getImage(snapshotImage, insideRect: firstPartFrame)
        let secondImage = getImage(snapshotImage, insideRect: secondPartFrame)

        let firstImageView = UIImageView(image: firstImage)
        let secondImageView = UIImageView(image: secondImage)

        if presenting {
            firstImageView.frame = CGRectOffset(firstPartFrame, 0, -CGRectGetHeight(firstPartFrame))
            secondImageView.frame = CGRectOffset(secondPartFrame, 0, CGRectGetHeight(secondPartFrame))
        } else {
            firstImageView.frame = CGRectOffset(firstPartFrame, -CGRectGetWidth(firstPartFrame), 0)
            secondImageView.frame = CGRectOffset(secondPartFrame, CGRectGetWidth(secondPartFrame), 0)
        }

        return (firstImageView, secondImageView)
    }

    func getImage(image: UIImage, insideRect rect:CGRect) -> UIImage {
        let image = CGImageCreateWithImageInRect(image.CGImage, rect)!
        return UIImage(CGImage: image)!
    }
}

class SecondViewController: UIViewController, UIViewControllerTransitioningDelegate {

    required init(coder aDecoder: NSCoder) {

        fatalError("init(coder:) has not been implemented")
    }

    init() {
        super.init(nibName: nil, bundle: nil)
        self.transitioningDelegate = self
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        let view1 = UIView(frame: CGRectZero)
        view1.backgroundColor = UIColor.purpleColor()
        view1.setTranslatesAutoresizingMaskIntoConstraints(false)

        let view2 = UIView(frame: CGRectZero)
        view2.backgroundColor = UIColor.cyanColor()
        view2.setTranslatesAutoresizingMaskIntoConstraints(false)

        view.addSubview(view1)
        view.addSubview(view2)

        let views = [
            "view1": view1,
            "view2": view2
        ]

        let vFormat = "V:|[view1][view2(==view1)]|"
        let hFormat = "H:|[view1]|"

        let hConstraints = NSLayoutConstraint.constraintsWithVisualFormat(hFormat,
            options: .allZeros,
            metrics: nil,
            views: views)
        let vConstraints = NSLayoutConstraint.constraintsWithVisualFormat(vFormat,
            options: .AlignAllLeft | .AlignAllRight,
            metrics: nil,
            views: views)

        view.addConstraints(hConstraints)
        view.addConstraints(vConstraints)

        let tapGestureRecognizer = UITapGestureRecognizer(target: self,
            action: "tapped")
        view.addGestureRecognizer(tapGestureRecognizer)
    }

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

    func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return AnimationController(presenting: false)
    }

    func tapped() {
        let nextViewController = NextViewController()
        dismissViewControllerAnimated(true, completion: nil)
    } 
}


class FirstViewController: UIViewController {

    override func viewDidLoad() {

        super.viewDidLoad()
        let view1 = UIView(frame: CGRectZero)
        view1.backgroundColor = UIColor.redColor()
        view1.setTranslatesAutoresizingMaskIntoConstraints(false)

        let view2 = UIView(frame: CGRectZero)
        view2.backgroundColor = UIColor.greenColor()
        view2.setTranslatesAutoresizingMaskIntoConstraints(false)

        view.addSubview(view1)
        view.addSubview(view2)

        let views = [
            "view1": view1,
            "view2": view2
        ]

        let hFormat = "H:|[view1][view2(==view1)]|"
        let vFormat = "V:|[view1]|"

        let hConstraints = NSLayoutConstraint.constraintsWithVisualFormat(hFormat,
            options: .AlignAllTop | .AlignAllBottom,
            metrics: nil,
            views: views)
        let vConstraints = NSLayoutConstraint.constraintsWithVisualFormat(vFormat,
                options: .allZeros,
                metrics: nil,
                views: views)

        view.addConstraints(hConstraints)
        view.addConstraints(vConstraints)

        let tapGestureRecognizer = UITapGestureRecognizer(target: self,
            action: "tapped")
        view.addGestureRecognizer(tapGestureRecognizer)

    }

    func tapped() {
        let secondViewController = SecondViewController()
        presentViewController(secondViewController, animated: true, completion: nil)
    }
}
Run Code Online (Sandbox Code Playgroud)

代码可能会更长一些,但必须易于理解。如果你愿意,稍微调整一下。