自定义presentViewController的转场动画(Swift)
原创Blog,转载请注明出处 我的StackFlow 前言:
Tips:所谓的转场上下文,就是转场的开始View和结束View,以及对应的ViewController 目标效果最终的效果 准备工作首先写出一个 点击某一个CollectionView Cell查看大图,再点击大图图片消失 这个最初的项目,可以在这里下载 CSDN下载 如何实现自定义转场动画
通过文档,可以看到
着两个方法的目的是,提供一个遵循 本文的设计是让 dvc.transitioningDelegate = self
然后,写一个extension来实现协议 extension ViewController:UIViewControllerTransitioningDelegate{
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return nil
}
func animationControllerForPresentedController(presented: UIViewController,presentingController presenting: UIViewController,sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return nil
}
}
这时候,再运行项目,会发现没有任何变化,还是默认的转场方式。因为我们还没有提供实际的动画 。当上述两个代理方法返回nil的时候,系统会使用默认的方式 实现UIViewControllerAnimatedTransitioning新建一个文件,命名为Animator.swift,然后新建一个类,处理Present的转场(Dismiss类似),实现UIViewControllerAnimatedTransitioning协议 class PresentAnimator: NSObject,UIViewControllerAnimatedTransitioning{
}
这时候,会报错没有实现协议,然后,我们添加协议方法,这时候的Animator.swift如下 import Foundation
import UIKit
class PresentAnimator: NSObject,UIViewControllerAnimatedTransitioning{
let duration = 0.5 //动画的时间
var originFrame = CGRectZero //点击Cell的frame
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return duration
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
}
}
简单介绍下这里的协议方法
转场的原理
所以,开发者要做的就是
实现实际的转场动画基于上述的原理,我们修改实际的动画 func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
let containView = transitionContext.containerView()
let toView = transitionContext.viewForKey(UITransitionContextToViewKey)!
let finalFrame = toView.frame
let xScale = originFrame.size.width/toView.frame.size.width
let yScale = originFrame.size.height/toView.frame.size.height
toView.transform = CGAffineTransformMakeScale(xScale,yScale)
toView.center = CGPointMake(CGRectGetMidX(originFrame),CGRectGetMidY(originFrame))
containView?.addSubview(toView)
UIView.animateWithDuration(duration,animations: { () -> Void in
toView.center = CGPointMake(CGRectGetMidX(finalFrame),CGRectGetMidY(finalFrame))
toView.transform = CGAffineTransformIdentity
}) { (finished) -> Void in
transitionContext.completeTransition(true)
}
}
然后,在ViewController.swfit中,添加一属性 let presentAnimator = PresentAnimator()
修改 override func collectionView(collectionView: UICollectionView,didSelectItemAtIndexPath indexPath: NSIndexPath) {
let dvc = DetailViewController()
dvc.image = UIImage(named: "image.jpg")
dvc.transitioningDelegate = self
let cell = collectionView.cellForItemAtIndexPath(indexPath) as! FullImageCell
presentAnimator.originFrame = cell.convertRect(cell.imageview.frame,toView: nil)
self.presentViewController(dvc,animated: true,completion: nil)
}
修改代理方法 func animationControllerForPresentedController(presented: UIViewController,sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return presentAnimator
}
这时候的动画效果如Gif 同理,为dismiss添加转场动画在Animator.swift中添加一个新的类 class DismisssAnimator:NSObject,UIViewControllerAnimatedTransitioning{
let duration = 0.6
var originFrame = CGRectZero
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return duration
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
let containView = transitionContext.containerView()
let toView = transitionContext.viewForKey(UITransitionContextToViewKey)! //Collection View
let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)! //全屏的imageview
let xScale = originFrame.size.width/toView.frame.size.width
let yScale = originFrame.size.height/toView.frame.size.height
containView?.addSubview(toView)
containView?.bringSubviewToFront(fromView)
UIView.animateWithDuration(duration,animations: { () -> Void in
fromView.center = CGPointMake(CGRectGetMidX(self.originFrame),CGRectGetMidY(self.originFrame))
fromView.transform = CGAffineTransformMakeScale(xScale,yScale)
}) { (finished) -> Void in
transitionContext.completeTransition(true)
}
}
}
然后,在ViewController.swift中 dismissAnimator.originFrame = cell.convertRect(cell.imageview.frame,toView: nil)
其中,dismissAnimator是ViewController的一个属性 let dismissAnimator = DismisssAnimator()
然后,在代理方法中,返回 func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return dismissAnimator;
}
最终的效果 完整工程的下载CSDN下载 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |