首页 > 解决方案 > 绘图动画在 Swift 中不起作用

问题描述

截屏

我创建了一个自定义 UIButton 类,在其中我用一种颜色填充它的内部,但只是部分填充。

目标:目标是用背景颜色填充按钮内部,但只是部分填充。例如,您有一个长按钮(高度:50.0,宽度:300.0)。我想用背景颜色水平填充它,假设只有 50%。在这种情况下,我的按钮只有一半会被颜色填充,另一半会保持透明或白色。

整个类看起来像这样:

class CustomButton: UIButton {

    var color: UIColor = .clear
    var percentage: CGFloat = 0

    func fill(withPercentage percentage: CGFloat, isCorrect correct: Bool, onRect rect: CGRect) {
        self.color = correct ? .lightishGreen : .pastelRed
        self.percentage = percentage

        draw(rect)
    }

    override func draw(_ rect: CGRect) {
        super.draw(rect)

        let fillRect = CGRect(
            origin: CGPoint(x: rect.origin.x, y: rect.origin.y),
            size: CGSize(width: rect.size.width * percentage, height: rect.size.height)
        )
        color.set()

        guard let context = UIGraphicsGetCurrentContext() else { return }
        context.fill(fillRect)
    }
}

这个类完美地工作。但是,我想为这个绘图过程设置动画,所以按钮填充了从 0.0 到 1.0 的背景颜色。

我试图把它放在context.fill(fillRect)里面,UIView.animate(){}但它没有用。所以我想知道,是否可以动画绘图?

我只是不想使按钮 bg 颜色清晰并将 UIView 放在它后面并在那里模拟填充。想要一个干净的方式。所以我会很高兴,如果有人可以给我一个提示或告诉我如何去做。提前致谢!

标签: iosswiftuiviewanimation

解决方案


听起来你想要一个自定义的动画属性。让我们称之为percentage。这是一种方法:

class MyView : UIView {
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        self.backgroundColor = .clear
    }
    override class var layerClass : AnyClass {
        return MyLayer.self
    }
    override func draw(_ rect: CGRect) {}
}
class MyLayer : CALayer {
    @NSManaged var percentage : CGFloat
    override class func needsDisplay(forKey key: String) -> Bool {
        if key == #keyPath(percentage) {
            return true
        }
        return super.needsDisplay(forKey:key)
    }
    override func action(forKey key: String) -> CAAction? {
        if key == #keyPath(percentage) {
            let ba = CABasicAnimation(keyPath: key)
            ba.fromValue = self.presentation()!.value(forKey:key)
            return ba
        }
        return super.action(forKey:key)
    }
    override func draw(in con: CGContext) {
        con.setFillColor(UIColor.green.cgColor)
        let rect = self.bounds.insetBy(dx: 2, dy: 2)
        let rounded = UIBezierPath.init(roundedRect: rect, cornerRadius: 20)
        con.addPath(rounded.cgPath)
        con.setStrokeColor(UIColor.lightGray.cgColor)
        con.strokePath()
        con.addPath(rounded.cgPath)
        con.clip(using: .evenOdd)
        let fillRect = CGRect(
            origin: CGPoint(x: rect.origin.x, y: rect.origin.y),
            size: CGSize(width: rect.size.width * percentage, height: rect.size.height)
        )
        con.fill(fillRect)
    }
}

结果是,当您设置此视图的 layerpercentage时,更改是动画的:

在此处输入图像描述


推荐阅读