iOS吃饭技巧Swift学习swift

Swift_ios_UIView动画,CA核心动画那些事(2)

2016-01-14  本文已影响1306人  ChinaSwift
秒学SWIFT

花了将近一周的时间去学习ios动画,因为对于一个ios开发者来说,动画内容绝对是一门必修课。听了不少课,也看了不少文章,终于对动画有了初步的了解和自己的一些小总结。但是傻傻笨笨的我,给自己挖了一个坑,为了填这个坑花了快两天时间,真够笨的!不过最终还是完美解决,小小成就感就来了!

关于动画,网上流传着许许多多的文章,基本上都适合初学者入门。那些文章大概思路都是这样的:
1.介绍什么是动画
2.动画可以分为UIView动画和CA动画。(其他动画暂时忽略)
3.UIView动画分为常规模式和闭包模式。现在主要用闭包模式。
4.UIView闭包模式有基本“杜蕾斯”动画,杜蕾斯弹性动画,转场动画,关键帧动画。
5.CA动画有基本动画,转场动画,关键帧动画,组动画,弹性动画。
6.UIView动画和CA动画的关系,即UIView动画是CA动画的封装。各有优势各有特色。

无可否认的是这些对自己在初步认识动画阶段,起到了很大的帮助作用,起码让自己对动画有个大概的了解。但是仅仅这些,还是会让初学者掉进坑里,比如我。所以学习动画以后的总结经验,就不可或缺了。这才不会让自己第二次掉进同一个坑。待会我要记录下自己怎么掉坑,填坑的。

我是先学习CA动画的,明白了CA动画能够细微调整的意义,也见识了CA动画是怎么让开发者去掌控每一个环节的。这个过程中我也笔记了基础的知识:(有一部分摘抄,一部分是自己总结)

//CAAnimation:
//所有动画对象的父类,负责控制动画的持续时间和速度,是个抽象类,不能直接使用,应该使用它具体的子类
//duration:动画的持续时间
//repeatCount:动画的重复次数
//repeatDuration:动画的重复时间
//removedOnCompletion:默认为YES,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。如果想让图层保持显示动画执行后的状态,那就设置为NO,不过还要设置fillMode为kCAFillModeForwards
//fillMode:决定当前对象在非active时间段的行为.比如动画开始之前,动画结束之后
//beginTime:可以用来设置动画延迟执行时间,若想延迟2s,就设置为CACurrentMediaTime()+2,CACurrentMediaTime()为图层的当前时间
//timingFunction:速度控制函数,控制动画运行的节奏
//delegate:动画代理
//keyPath: 通过指定CALayer的一个属性名称达到相应的动画效果,比如说,指定"position"为keyPath,就修改CALayer的position属性值,以达到平移的动画效果


//A. CGAffineTransform
//从CG就可以看出它是属于Core Graphics的东西,实际上UIView的transform属性就是CGAffineTransform类型,用它可以做二维平面上的缩放、旋转、平移。
//B.CATransform3D(layer)
//它可以做到让图层在三维空间内平移、旋转等。

以上是CA动画的类型,我学习完它再去学UIView动画,所以知道UIView动画其实就是CA动画的封装,优点是快捷方便,UIView的弹性动画完美体现了这点。缺点是不能细微调整。这里不作UIView的详细介绍。

虽然UIView动画是对CA核心动画的封装,但还是有必要对他们加以总结,这可是目前在网上找不到的宝贵经验哦!(经验可能有误,欢迎指正)

//UIView的动画跟CAAnimation动画的异同:
//1.都能控制动画开始执行时刻。uiview的delay。CA中的beginTime。
//2.都能在动画结束后实现控制。uiview有闭包。CA中有代理函数didFinish。
//3.uiView有弹性动画和关键帧动画,CA中也有,而且更为丰富。
//4.uiView组合动画用cgaffinetransformconcat。CA中用CAanimationGroup,并支持多组合。
//    uiview 的多组合则可以通过创建多个uiview.animation来实现。多是指两个以上。
//    这里的组合是指为同一个对象的不同属性进行组合。
//    如果是不同对象要实现同一个动画,则直接在uiview的内容中添加。或者直接在CA中赋予多个对象的layer。
//5.uiView实现2D或者3D动画,取决于里面设置的动画属性。若设置的是layer层,则可以实现3D动画。(rotation属性可以体现)
//  CA动画则取决于key。如果是transform,则可以3D.如果是transform.rotation,则可以是2D。
//    CA中transform属性有rotation,scale,translation。
//    CA中key还可以是bounds,position,opacity。这里的position等价于uiview的center。
//6.uiview动画完毕之后属性已经更改。CA动画则不会改变实际位置,即使表面改变了。

下面我则要记录下我在学习UIView动画的时候是怎么给自己挖坑的,并怎么最终把坑填上获得小小成就感的。其实当完美解决问题的那一刻,发现代码是如此的简单,可就为了那一段代码,让我费劲了力气,花尽了脑汁才得以解决。只怪自己经验不足咯!都说怪我咯希望能帮助到有同样困惑的人儿

关键字:中断,终止,中止,取消,停止UIView动画

问题发现:

问题起源:

问题解决:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {      
        self.textView?.layer.removeAllAnimations()
        self.animation()   
    }

可是问题真的解决了吗?当然不是。添加后的现象是我再次触发时,动画立马停止了。看起来后面self.animation()并没有执行一样。

问题回首:

有了UIView动画的填坑经验,我自个再到CA中去解决类似问题就迎刃而解了!什么?刚刚不是说CA中不存在这种问题吗??这里有必要说明一点,就是当CA动画是非无止境动画(就是会停止的动画),在还没停止之前再次触发,是不会发生这些错乱问题的。

然而要是CA动画是个无止境的动画,也就是如果动画委托协议的animationDidStop中再次调用动画函数的话,这时再来个触发相同动画,动画就是乱得一塌糊涂了!接下来就记录一下怎么轻松解决这个问题的。
   @IBAction func next(sender: AnyObject) {
    self.transition()
    }

  func transition(){
    let transition = CATransition()
    transition.delegate = self
    //动画过渡类型
    transition.type = "pageCurl"
    
    //动画过渡类型方向
    transition.subtype = kCATransitionFromLeft
    
    transition.duration = 1
    
    transition.setValue("second", forKey: "whichAnimation")
    
    self.iv.layer.addAnimation(transition, forKey: nil)
  }

  override func animationDidStop(anim: CAAnimation, finished flag: Bool) {
        switch anim.valueForKey("whichAnimation") as! String{
        case "one"    :
                        print("hello")         
        case "second" :
                        print("finish")    
                        self.next("repeat")
        default :print("grandre")
        }
  }

这样的代码确实能够运行,能够循环调用动画,实现无止境。但是问题是当再次点击按键触发动画的话,这代码的bug就一漏无遗了。




谨以此文章记录自己在学习动画路上遇到的问题,也希望能够通过分享总结,分享故事帮助到碰上同样问题的人儿。
上一篇 下一篇

猜你喜欢

热点阅读