带Swift3的CALayer +隐式动画子类 [英] Subclassing CALayer + Implicit Animation w/ Swift3

查看:54
本文介绍了带Swift3的CALayer +隐式动画子类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过重写CALayer来实现隐式动画。我通读了文档,发现它相当复杂。而且,我找不到任何不错的代码示例,也找不到很好的解释或使用任何Swift的互联网帖子。

I am trying to implement "implicit animations" by overriding CALayer. I've read through the documentation and find it rather complicated. More over, I can't find any decent code examples, or internet posts explaining it well or using any Swift.

我由子类 BandBaseCG 实现,该子类试图为属性 param1提供隐式动画,并覆盖了 needsDisplay(forKey:),它的确会用我的属性调用一次,并返回true。

I've implemented by subclass BandBaseCG which attempts to provide implicit animation for property param1, and overridden needsDisplay(forKey:) which does get called once with my property where I return true.

但是这里出了问题。我的理解是,我必须返回一个符合 CAAction 协议的对象,比如说 CABasicAnimation ,这就是我的目的做。但是, action(forKey:) defaultAction(forKey:)不会与 param1 键。

But here is where it goes wrong. My understanding is that I must return an object conforming to the CAAction protocol, say a CABasicAnimation, and this is what I do. However, action(forKey:) or defaultAction(forKey:) do not get called with the param1 key.

因此,我了解到可以在 draw(ctx:)中提供Core-Graphics绘图代码响应某些 layer.param1 = 2 来实现实际的隐式动画。但是我到此为止,因为API根本无法按我预期的那样工作。

So I understand that at some point I can provide Core-Graphics drawing code in draw(in ctx:) to implement the actual implicit animation in response to some layer.param1 = 2. But I just cannot get to this point because the API is simply not working how I expected.

这是我当前的实现方式:

Here is my current implementation:

import Foundation
import QuartzCore

class BandBaseCG: CALayer {

   @NSManaged var param1: Float

   override init(layer: Any) {

      super.init(layer: layer)

   }

   override init() {
      super.init()

   }

   required init?(coder aDecoder: NSCoder) {
      fatalError("init(coder:) has not been implemented")
   }


   override func action(forKey event: String) -> CAAction? {

      print(event)

      if event == "param1" {

         let ba = CABasicAnimation(keyPath: event)
         ba.duration = 2
         ba.fromValue = (presentation()! as BandBaseCG).param1
         ba.toValue = 2

         return ba
      }

      return super.action(forKey: event)
   }


   override func draw(in ctx: CGContext) {
      print("draw")
   }


   override class func defaultAction(forKey event: String) -> CAAction?     {

      if event == "param1" {

         let ba = CABasicAnimation(keyPath: event)
         ba.duration = 2
         ba.fromValue = 0
         ba.toValue = 2

         return ba
      }

      return super.defaultAction(forKey: event)
   }

   override class func needsDisplay(forKey key: String) -> Bool {

      print(key)

      if key == "param1" {
         return true
      }

      return super.needsDisplay(forKey: key)
   }

   override func display() {
      print("param value: \(param1)")
   }

}


推荐答案

工作示例(来自我的书):

Here's a complete working example (from my book):

class MyView : UIView { // exists purely to host MyLayer
    override class var layerClass : AnyClass {
        return MyLayer.self
    }
    override func draw(_ rect: CGRect) {} // so that layer will draw itself
}
class MyLayer : CALayer {
    @NSManaged var thickness : CGFloat
    override class func needsDisplay(forKey key: String) -> Bool {
        if key == #keyPath(thickness) {
            return true
        }
        return super.needsDisplay(forKey:key)
    }
    override func draw(in con: CGContext) {
        let r = self.bounds.insetBy(dx:20, dy:20)
        con.setFillColor(UIColor.red.cgColor)
        con.fill(r)
        con.setLineWidth(self.thickness)
        con.stroke(r)
    }
    override func action(forKey key: String) -> CAAction? {
        if key == #keyPath(thickness) {
            let ba = CABasicAnimation(keyPath: key)
            ba.fromValue = self.presentation()!.value(forKey:key)
            return ba
        }
        return super.action(forKey:key)
    }
}

您会发现,如果将MyView放入应用程序中,则可以说

You will find that if you put a MyView into your app, you can say

let lay = v.layer as! MyLayer
lay.thickness = 10 // or whatever

它将使更改生效在边框的厚度。

and that it will animate the change in the border thickness.

这篇关于带Swift3的CALayer +隐式动画子类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆