自定义UIView中的动画setFillColor颜色更改

时间:2018-07-10 14:48:02

标签: ios swift animation

我有一个名为UIView的自定义CircleView,它实际上是一个彩色的椭圆。我用来为椭圆着色的color属性是在图形上下文上使用setFillColor呈现的。我想知道是否有一种方法可以对颜色变化进行动画处理,因为当我执行动画/过渡时,颜色变化会立即变为动画而不是动画。

示例设置

let c = CircleView()
c.frame = CGRect(x: 20, y: 20, width: 100, height: 100)
c.color = UIColor.blue
c.backgroundColor = UIColor.clear
self.view.addSubview(c)

UIView.transition(with: c, duration: 5, options: .transitionCrossDissolve, animations: {
    c.color = UIColor.red // Not animated
})

UIView.animate(withDuration: 5) {
    c.color = UIColor.yellow // Not animated
}

圈子视图

class CircleView : UIView {

    var color = UIColor.blue {
        didSet {
            setNeedsDisplay()
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func draw(_ rect: CGRect) {

        guard let context = UIGraphicsGetCurrentContext() else {return}

        context.addEllipse(in: rect)
        context.setFillColor(color.cgColor)
        context.fillPath()

    }
}

2 个答案:

答案 0 :(得分:1)

您可以将内置的动画支持用于图层的data_t$ndays
制作圆圈最简单的方法是将视图变成正方形(例如,使用宽高比约束),然后将backgroundColor设置为宽度或高度的一半,但我想您需要更高级的东西,这就是为什么您使用路径的原因。 我对此的解决方案将是:

cornerRadius

或者,如果您真的需要一个简单的圆圈,就像这样:

class CircleView : UIView {

var color = UIColor.blue {
    didSet {
        layer.backgroundColor = color.cgColor
    }
}

override init(frame: CGRect) {
    super.init(frame: frame)
    setup()
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    setup()
}

// Setup the view, by setting a mask and setting the initial color
private func setup(){
    layer.mask = shape
    layer.backgroundColor = color.cgColor
}

// Change the path in case our view changes it's size
override func layoutSubviews() {
    super.layoutSubviews()
    let path = CGMutablePath()
    // add an elipse, or what ever path/shapes you want
    path.addEllipse(in: bounds)
    // Created an inverted path to use as a mask on the view's layer
    shape.path = UIBezierPath(cgPath: path).reversing().cgPath
}
// this is our shape
private var shape = CAShapeLayer()
}

无论哪种方式,都可以很好地制作动画:

class CircleView : UIView {

var color = UIColor.blue {
    didSet {
        layer.backgroundColor = color.cgColor
    }
}

override init(frame: CGRect) {
    super.init(frame: frame)
    setup()
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    setup()
}

private func setup(){
    clipsToBounds = true
    layer.backgroundColor = color.cgColor
}

override func layoutSubviews() {
    super.layoutSubviews()
    layer.cornerRadius = bounds.height / 2
}
}

答案 1 :(得分:1)

奇怪的事情发生了!

您的代码没问题,您只需要异步地调用动画即可

如您所见,使用

let c = CircleView()

override func viewDidLoad() {
    super.viewDidLoad()
    c.frame = CGRect(x: 20, y: 20, width: 100, height: 100)
    c.color = UIColor.blue
    c.backgroundColor = UIColor.clear
    self.view.addSubview(c)
    changeColor()
}


func changeColor(){
    DispatchQueue.main.async
    {
        UIView.transition(with: self.c, duration: 5, options: .transitionCrossDissolve, animations: {
            self.c.color = UIColor.red // Not animated
        })

        UIView.animate(withDuration: 5) {
            self.c.color = UIColor.yellow // Not animated
        }
    }
}

发挥魅力。 即使您添加了触发颜色变化的按钮,按下按钮时动画也将起作用。

我建议您在CircleView的定义中设置此方法

func changeColor(){
    DispatchQueue.main.async
        {
            UIView.transition(with: self, duration: 5, options: .transitionCrossDissolve, animations: {
                self.color = UIColor.red 
            })

            UIView.animate(withDuration: 5) {
                self.color = UIColor.yellow 
            }
    }
}

,只需使用

即可在ViewController中的所需位置调用它
c.changeColor()