iOS 卡片转场动画 Swift

        最近 产品要iOS 使用 Google那套 Material Design   ,所以 就研究实现相关的 动画逻辑,具体 什么设计咱不谈了。

说说需求吧:两个控制器之间需要有一些连接,比如,卡片 飞入。卡片是A,B的共同元素。

       然后 就用Swift写了一个,OC版的 已经有大神写了,我在下面的连接 有跳转。

       先看效果吧:


       

     

      主要实现就是 实现了 分别为push 和 pop 实现了 UIViewControllerAnimatedTransitioning 协议,并在相关方法中完成动画设计。

     1、push动画

//
//  JYMagicMoveTransion.swift
//  JYMagicMove
//
//  Created by 杨勇 on 16/8/16.
//  Copyright © 2016年 JackYang. All rights reserved.
//

import UIKit

class JYMagicMoveTransion: NSObject ,UIViewControllerAnimatedTransitioning{
    
    func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
        return 0.5;
    }
    
    func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
        
        //拿到 fromVC 和 toVC 以及 容器
        let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) as! ViewController
        let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) as! JYDetailController
        let container = transitionContext.containerView();
        
        //拿到 cell上的 imageView的快照 隐藏 cell上的imageView
        let snapshotView = fromVC.selectCell.imageView.snapshotViewAfterScreenUpdates(false)
        //设置快照的frame
        snapshotView.frame = container!.convertRect(fromVC.selectCell.imageView.frame, fromView: fromVC.selectCell.imageView.superview)
        //隐藏
        fromVC.selectCell.imageView.hidden = true
        
        //设置toVC 的位置 并设置为透明
        toVC.view.frame = transitionContext.finalFrameForViewController(toVC)
        toVC.view.alpha = 0
        toVC.avaterImageView.hidden = true
        
        //把 toVC的 view 和 快照 加到 容器 上,顺序!
        container?.addSubview(toVC.view)
        container?.addSubview(snapshotView)
        
        //做动画前先把avaterImageView 的frame 更新一下 不然 storyboard 尺寸没有更新
        toVC.avaterImageView.layoutIfNeeded()
        UIView.animateWithDuration(transitionDuration(transitionContext), delay: 0, options: UIViewAnimationOptions.CurveEaseInOut, animations: { 
            () -> Void in
            //动画
            snapshotView.frame = toVC.avaterImageView.frame
            toVC.view.alpha = 1
        }) { (finish:Bool) -> Void in
            fromVC.selectCell.imageView.hidden = false // 把之前隐藏的 显示出来
            toVC.avaterImageView.hidden = false
            snapshotView.removeFromSuperview()
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
        }
    }
    
}

     代码注释的比较详细,我不在冗余的介绍。


    2、pop动画(注释较少,主要是和push基本逻辑相等。)

   

//
//  JYMagicPopTransion.swift
//  JYMagicMove
//
//  Created by 杨勇 on 16/8/16.
//  Copyright © 2016年 JackYang. All rights reserved.
//

import UIKit

class JYMagicPopTransion: NSObject ,UIViewControllerAnimatedTransitioning{
    
    func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
        return 0.5
    }
    
    func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
        
        //拿到 fromVC 和 toVC 以及 容器
        let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) as! JYDetailController
        let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) as! ViewController
        let container = transitionContext.containerView()
        
        //拿到快照
        let snapshotView = fromVC.avaterImageView.snapshotViewAfterScreenUpdates(false)
        snapshotView.frame = container!.convertRect(fromVC.avaterImageView.frame, fromView: fromVC.avaterImageView.superview)
        fromVC.avaterImageView.hidden = true
        
        toVC.view.frame = transitionContext.finalFrameForViewController(toVC)
        toVC.selectCell.imageView.hidden = true
        
        container?.insertSubview(toVC.view, belowSubview: fromVC.view)
        container?.addSubview(snapshotView)
        
        UIView.animateWithDuration(transitionDuration(transitionContext), delay: 0, options: UIViewAnimationOptions.CurveEaseInOut, animations: { 
            () -> Void in
            snapshotView.frame = container!.convertRect(toVC.selectCell.imageView.frame, fromView: toVC.selectCell.imageView.superview)
            fromVC.view.alpha = 0
        }) { (finish: Bool) -> Void in
            toVC.selectCell.imageView.hidden = false
            snapshotView.removeFromSuperview()
            fromVC.avaterImageView.hidden = false
            
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
        }
        
    }
}

    3、第三点就是滑动 的进度 我通过UIPercentDrivenInteractiveTransition实现。并且 给 第二个控制器加一个 手势(UIScreenEdgePanGestureRecognizer)

//
//  JYDetailController.swift
//  JYMagicMove
//
//  Created by 杨勇 on 16/8/16.
//  Copyright © 2016年 JackYang. All rights reserved.
//

import UIKit

class JYDetailController: UIViewController ,UINavigationControllerDelegate{

    @IBOutlet weak var avaterImageView: UIImageView!
    
    private var percentDrivenTransition :UIPercentDrivenInteractiveTransition?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.navigationController?.delegate = self
        let edgePan = UIScreenEdgePanGestureRecognizer.init(target: self, action:Selector("edgePanGesture:"))
        edgePan.edges = UIRectEdge.Left
        self.view.addGestureRecognizer(edgePan)
    }
    
    func edgePanGesture(edgePan:UIScreenEdgePanGestureRecognizer){
        let progress = edgePan.translationInView(self.view).x / self.view.bounds.width
        if edgePan.state == UIGestureRecognizerState.Began {
            self.percentDrivenTransition = UIPercentDrivenInteractiveTransition()
            self.navigationController?.popViewControllerAnimated(true)
        } else if edgePan.state == UIGestureRecognizerState.Changed {
            self.percentDrivenTransition?.updateInteractiveTransition(progress)
        } else if edgePan.state == UIGestureRecognizerState.Cancelled || edgePan.state == UIGestureRecognizerState.Ended {
            if progress > 0.5 {
                self.percentDrivenTransition?.finishInteractiveTransition()
            } else {
                self.percentDrivenTransition?.cancelInteractiveTransition()
            }
            self.percentDrivenTransition = nil
        }
    }

    func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        if operation == UINavigationControllerOperation.Pop {
            return JYMagicPopTransion()
        } else {
            return nil
        }
    }
    
    func navigationController(navigationController: UINavigationController, interactionControllerForAnimationController animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
        if animationController is JYMagicPopTransion {
            return self.percentDrivenTransition
        } else {
            return nil
        }
    }
    
}
    可以看到,不断更新 progress,然后把percentDrivenTransition 通过 navigation的代理告诉它,完成动画更新。

    OC版 是 KittenYang写的,我参考他的。原文有下载地址。


你可能感兴趣的:(iOS,animation,Swift学习笔记)