2017-05-26 89 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。 –