2017-05-26 94 views
1

我有一個UIView,正在爲我完成所有的繪圖。所以現在當我改變我的視圖的值時,它會將其轉發給圖層。而當我在UIView-Animaiton Block中時,我希望這種變化能夠成爲動畫。自定義CALayer動畫

所以我現在做的事:

class SampleView: UIView { 
    var myProperty: CGFloat { 
     set { 
      sampleLayer.myProperty = newValue 
     } 
     get { 
      return sampleLayer.myProperty 
     } 
    } 

    override class var layerClass: AnyClass { 
     return SampleViewLayer.self 
    } 

    private var sampleLayer: SampleViewLayer { 
     return layer as! SampleViewLayer 
    } 
} 

class SampleViewLayer: CALayer { 
    @NSManaged public var myProperty: CGFloat 

    override func draw(in ctx: CGContext) { 
     // Incredible beautiful drawing is happening here depending on myProperty 
    } 

    override static func needsDisplay(forKey key: String) -> Bool { 
     if key == "myProperty" { 
      return true 
     } 
     return super.needsDisplay(forKey: key) 
    } 

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

     if event == "myProperty" { 

      // 1. How do I find out if the change should be animated? 

      let animation = CABasicAnimation(keyPath: event) 
      animation.fromValue = presentation()?.value(forKey: event) 

      // 2. How do I find out the proper timingFunction as well as the proper duration? 
      animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) 
      animation.duration = 1.0 

      return animation 
     } 

     return super.action(forKey: event) 
    } 
} 

而且我希望能夠以動畫這樣的:

.... 
instanceOfMySampleView.myProperty = 0 // inital value should be set without animation 
UIView.animate(withDuration: 4, animations: { 
    self.instanceOfMySampleView.myProperty = 10 // should animate to this value 
}) 
.... 

所以兩個實際的問題是我的示例代碼中... 1.我如何知道更改是否應該動畫化?那麼如何弄清楚它發生在UIView-Animation-Block內部?

  1. 如果它是動畫,如何找到持續時間和timing功能的正確參數?

另外。如果我在代碼中創建View的實例,將它的myProperty值設置爲初始值,然後直接執行UIViewAnimationBlock,則PresentationLayer將爲零,所以我的動畫將無法正常工作...

回答

2

除非發生了一些變化自從我上次查看它之後,我會說你無法獲得這些值。可惜沒有API提供它。

如果您對動畫視圖的調用是手動的(您正在調用這些動畫),那麼我建議您將所有這些調用替換爲一些自定義調用。像AnimationManager.animate(withDuration:...這種方法然後調用UIView相應的方法,因此您需要用這些方法替換所有的呼叫。一旦完成,您應該看到與您目前相同的結果。

現在,您需要添加邏輯到這段代碼保存曲線值,持續時間......基本實現是一旦結束(不完成保存新值,當動畫塊開始,然後將其刪除但動畫塊中的最後一行)。

有點複雜的系統是創建一個堆棧(數組應該這樣做)的設置,而不是一個單一的值。開始時你添加一個對象,最後你只需刪除它。原因是動畫調用可能是嵌套的,只是刪除動畫設置可能不夠。第二個原因是您可能還需要添加功能performWithoutAnimations,這也是UIView,在這種情況下,您只需將空對象追加到堆棧。

在任何的2例,那麼你可能會得到AnimationManager.isAnimatingAnimationManager.animationDurationAnimationManager.animationCurve ...因此,這從您自己的電話給動畫作品很好。但是爲了使這個一般(例如在設備方向改變)似乎是一個相當大的問題。我很確定這些數據必須在某處,並且很樂意訪問它們。

我希望這個系統可以幫助您,除非您找到更合適的解決方案。

+0

好吧,不是我希望的答案,但謝謝你的幫助!我會稍微等一下,看看其他人是否可能知道是否/在哪裏訪問這些值,如果沒有,我當然會接受你的答案!謝謝! – Georg

+0

@Georg同意,把它留在這裏,希望有更好的一個。不過,我建議你無論如何都要把它包起來。至少你可以在這裏設置默認值,例如動畫持續時間。人們傾向於在整個應用程序中粘貼相同的值。所以基本上你可以實現整個事情,如果你找到一個合適的解決方案,你需要做的就是改變屬性的getters。 –