iOS自定义控件与效果ios闲来一看iOS

swift10分钟实现炫酷的导航控制器跳转动画

2015-08-19  本文已影响7808人  codeGlider
最终效果
在开始前需要下载该教程的初始项目,点击下面的地址来下载
初始项目github地址
当然你也可以在文章结尾找到完成后的项目,但是我还是建议你一步一步跟着我的教程去编写代码,这样可以更好地掌握它们 : )

导航控制器的工作原理

导航控制器
导航控制器使用一种叫做导航栈的东西来控制导航,用一个由多个视图控制器组成的数组来表示,如下图所示:
导航栈
导航控制器能进行两个操作,Push(压栈),Pop(出栈),实际上都是对导航栈进行操作 导航栈压栈操作 导航栈出栈操作

如何自定义导航栏跳转

是这样的,UIKIt是通过代理模式来自定义导航控制器跳转动画,每次运行页面跳转动画时,UIKit都会去检查它的UINavigationControllerDelegate代理中的方法func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning
的返回值,如果是nil的话,就会执行系统默认的动画
如果返回值是一个实现了UIViewControllerAnimatedTransitioning协议的NSObject,也就是我们将要创建的自定义动画控制器Animator,则会执行我们的自定义动画

所以总结一下,我们要自定义跳转动画的话需要这么几个步骤:

1. 创建自定义的动画类,并实现UIViewControllerAnimatedTransitioning协议

2. 让导航跳转的起始视图控制器和终点视图控制器都实现UINavigationControllerDelegate代理

3. 具体实现动画内容,主要在UIViewControllerAnimatedTransitioning协议中的animateTransition()方法中实现

so,我们知道了原理,也知道大概实现的步骤了,下面就开始写代码了!

开始写代码( ⊙ o ⊙ )。。。

首先创建我们的自定义动画类RevealAnimator(创建一个RevealAnimator.swift文件)让它成为NSObject的子类,并实现UIViewControllerAnimatedTransitioning协议
就像这样:

 class RevealAnimator: NSObject,UIViewControllerAnimatedTransitioning {
     
 }

当然你还需要实现该协议的两个必须实现的方法
transitionDuration()animateTransition()

首先添加一些必要的变量:

let animationDuration = 2.0

var operation:UINavigationControllerOperation = .Push

第一个长量用来确定动画的时长(2秒算是比较长的时间,为了是能够更好地观察动画效果);operation变量用来确定当前跳转动画是push还是pop一个视图控制器

然后再去实现这两个方法,返回我们定义的常量来设置动画的时长

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

然后打开我们的主视图控制器MasterViewController.swift

在扩展里让当前类遵循导航控制器的代理协议UINavigationControllerDelegate

记得在viewDidLoad()里将导航控制器的代理设置为当前视图控制器

navigationController?.delegate = self

下面创建我们自定义动画类的一个实例

let transition = RevealAnimator()

实现代理的方法,并将我们自定义的动画类实例作为返回值返回

func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
  transition.operation = operation
    
    return transition
    
}

这一长串参数的方法是不是很唬人?不用怕,下面我们来详细解释一下这个方法的参数:

不过目前我们的动画类还是一个空壳,so现在去完成它吧~

实现push动画代码

打开RevealAnimator.swift,添加一个变量

weak var storedContext: UIViewControllerContextTransitioning?

因为你要为跳转动画创建一些图层动画,所以你要在动画结束前(也就是代理方法animationDidStop()执行之前)将跳转的上下文保存起来,对其进行一些操作

在animateTransition()中保存跳转的上下文

storedContext = transitionContext

下面真正开始添加动画的代码

好的,到目前为止你的动画类就编写完成了~

当然我们的遮罩图层还没有进行配置
打开DetailViewController.swift,在viewDidLoad()方法中配置遮罩图层:

 maskLayer.position = CGPoint(x: view.layer.bounds.size.width/2,y: view.layer.bounds.size.height/2)
 view.layer.mask = maskLayer

将遮罩图层在视图中居中,并将图层的遮罩设置为我们自定义的遮罩,也就是swift logo的形状

最后在视图控制器完全显现后,除去遮罩图层,在viewDidAppear()中添加如下代码:

view.layer.mask = nil

到目前为止我们的导航控制器的push动画部分就完成了。

实现pop动画代码

pop动画部分就相对比较简单了

首先用一个if语句将以上push动画部分( )包裹起来:

if operation == .Push {
storedContext = transitionContext
   ....................
  toVC.view.layer.addAnimation(fadeInAnimation, forKey: nil)
}else{

//这里添加pop动画的实现代码

}

在注释处添加一些代码

        let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)! as UIView
        
        let toView = transitionContext.viewForKey(UITransitionContextToViewKey)! as UIView
        
        transitionContext.containerView().insertSubview(toView, belowSubview: fromView)
       
        UIView.animateWithDuration(animationDuration, animations: { () -> Void in
         fromView.transform = CGAffineTransformMakeScale(0.1, 0.1)
            fromView.alpha = 0.0
            
        }, completion: { (finish) -> Void in
    transitionContext.completeTransition(true)
            
        })

这段代码看起来和push部分很像,但是要注意的一点是,pop动画进行的时候是无法对视图控制器进行操作的,只能对他们的视图进行操作:

 let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)! as UIView
        
let toView = transitionContext.viewForKey(UITransitionContextToViewKey)! as UIView

所以这里取出的是UIView

这段代码也需要说明一下,这段代码做的是把pop动画的初始视图放在了目的视图之下,因为我们要实现的效果是初始视图缩小消失,最后完全露出目的视图

 transitionContext.containerView().insertSubview(toView, belowSubview: fromView)

现在整个项目应该可以完整地运行了~push动画和pop动画都可以进行

push pop
如果你遇到了一些错误,或者是动画效果没有实现,请下载完整项目来检查一下:
完整项目

此教程翻译自iOS Animations by Tutorials v1.4 第20章的内容,根据自己的理解做了一些改变,包括绘制swift的logo,关于如何绘制这个logo请继续关注我的文章,下一个教程会告诉你如何快速得到绘制代码!

如果本篇文章对你有帮助,可以点一下左下角的喜欢,大家的支持与鼓励是继续写作的动力~

上一篇下一篇

猜你喜欢

热点阅读