【问题标题】:Custom CALayer Animation自定义 CALayer 动画
【发布时间】:2017-05-26 09:25:11
【问题描述】:

我有一个 UIView,它有一个图层为我做所有的绘图。因此,现在当我更改视图的值时,它会将其转发到图层。当我在 UIView-Animaiton 块中时,我希望该更改具有动画效果。

那么我目前在做什么:

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. 如果是动画,如何为 duration 和 timingFunction 找到合适的参数?

还有。如果我在代码中创建我的视图实例,将其 myProperty 值设置为初始值,然后直接执行 UIViewAnimationBlock,PresentationLayer 将为 nil,因此我的动画将无法正常工作...

【问题讨论】:

    标签: ios calayer uiviewanimation caanimation


    【解决方案1】:

    除非自从我上次调查以来已经进行了一些更改,否则我会说您无法获得这些值。可惜没有提供API。

    如果您对动画视图的调用是手动的(您正在调用这些动画),那么我建议您将所有这些调用替换为一些自定义调用。像AnimationManager.animate(withDuration:... 这个方法然后调用UIView 对应的方法,所以你需要用这些替换所有的调用。完成后,您应该会看到与当前相同的结果。

    现在您需要在此代码中添加逻辑以保存曲线的值、持续时间...一个基本实现是在动画块开始时保存新值,然后在结束时将其删除(不是在完成时,而是动画块中的最后一行)。

    一个更复杂的系统是创建一个设置的堆栈(数组应该做)而不是单个值。开始时您添加一个对象,最后您只需将其删除。这样做的原因是动画调用可能是嵌套的,仅仅删除动画设置可能还不够。第二个原因是您可能还需要添加功能performWithoutAnimations,它也在UIView 上,在这种情况下,您只需将一个空对象附加到堆栈。

    在这两种情况中的任何一种情况下,您都可能得到AnimationManager.isAnimatingAnimationManager.animationDurationAnimationManager.animationCurve...所以这可以很好地通过您自己对动画的调用来实现。但是要使其通用(例如在设备方向更改时)似乎是一个很大的问题。我很确定这些数据一定在某个地方,并且很乐意访问它们。

    除非您找到更合适的解决方案,否则我希望此系统对您有所帮助。

    【讨论】:

    • 好的,不是我希望的答案,但感谢您的帮助!!!我会等一下,看看其他人是否知道是否/在哪里访问这些值,如果不是,我当然会接受你的回答!谢谢!
    • @Georg 同意,把它留在这里,希望有一个更好的。不过我还是建议你把它包起来。至少你可以在这里为动画持续时间等设置默认值。人们倾向于在整个应用程序中粘贴相同的值。所以基本上你已经可以实现整个事情了,如果你找到了一个合适的解决方案,你需要做的就是改变属性的 getter。
    猜你喜欢
    • 2011-03-11
    • 2011-01-24
    • 1970-01-01
    • 2015-08-13
    • 2011-05-06
    • 2013-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多