使用Button自定义CAShapeLayer动画

时间:2016-03-29 08:55:13

标签: ios swift animation cashapelayer

我通过更改自动布局的约束并使用UIView动画块为其设置动画来设置我的按钮的动画:

UIView.animateWithDuration(0.5, animations: { self.layoutIfNeeded() })

在此动画中,只有按钮的宽度正在变化,而按钮本身也是动画。

在我的按钮中,有一个自定义CAShapeLayer。是否可以捕捉按钮的动画并将其添加到图层,以便与按钮一起动画?

我尝试过的事情:

// In my CustomButton class
override func actionForLayer(layer: CALayer, forKey event: String) -> CAAction? {

    if event == "bounds" {
        if let action = super.actionForLayer(layer, forKey: "bounds") as? CABasicAnimation {
        let animation = CABasicAnimation(keyPath: event)
        animation.fromValue = border.path
        animation.toValue = UIBezierPath(rect: bounds).CGPath

        // Copy values from existing action

        border.addAnimation(animation, forKey: nil) // border is my CAShapeLayer
    }

    return super.actionForLayer(layer, forKey: event)
}

// In my CustomButton class
override func layoutSubviews() {
    super.layoutSubviews()

    border.frame = layer.bounds

    let fromValue = border.path
    let toValue = UIBezierPath(rect: bounds).CGPath

    CATransaction.setDisableActions(true)
    border.path = toValue

    let animation = CABasicAnimation(keyPath: "path")
    animation.fromValue = fromValue
    animation.toValue = toValue
    animation.duration = 0.5

    border.addAnimation(animation, forKey: "animation")
}

没有什么工作,我已经挣扎了好几天..

的CustomButton:

class CustomButton: UIButton {

    let border = CAShapeLayer()

    init() {
        super.init(frame: CGRectZero)

        translatesAutoresizingMaskIntoConstraints = false
        border.fillColor = UIColor.redColor().CGColor
        layer.insertSublayer(border, atIndex: 0)
    }

//  override func layoutSubviews() {
//      super.layoutSubviews()
//      
//      border.frame = layer.bounds
//      border.path = UIBezierPath(rect: bounds).CGPath
//  }

    override func layoutSublayersOfLayer(layer: CALayer) {
        super.layoutSublayersOfLayer(layer)

        border.frame = self.bounds
        border.path = UIBezierPath(rect: bounds).CGPath
    }
}

1 个答案:

答案 0 :(得分:1)

当您调整视图的背衬图层时,您所要做的就是调整子图层的大小。由于implicit animation,更改应该是动画的。所以你需要做的就是在自定义视图类中设置它:

override func layoutSublayersOfLayer(layer: CALayer!) {
    super.layoutSublayersOfLayer(layer)
    border.frame = self.bounds
}

<强>更新

我有时间玩动画,现在似乎对我有用。这就是它的样子:

class TestView: UIView {

    let border = CAShapeLayer()

    init() {
        super.init(frame: CGRectZero)

        translatesAutoresizingMaskIntoConstraints = false
        border.backgroundColor = UIColor.redColor().CGColor
        layer.insertSublayer(border, atIndex: 0)
        border.frame = CGRect(x: 0, y:0, width: 60, height: 60)

        backgroundColor = UIColor.greenColor()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }


    override func layoutSublayersOfLayer(layer: CALayer) {
        super.layoutSublayersOfLayer(layer)

        CATransaction.begin();
        CATransaction.setAnimationDuration(10.0);
        border.frame.size.width = self.bounds.size.width
        CATransaction.commit();
    }

}

我这样使用它:

var tview: TestView? = nil
override func viewDidLoad() {
    super.viewDidLoad()

    tview = TestView();
    tview!.frame = CGRect(x: 100, y: 100, width: 60, height: 60)
    view.addSubview(tview!)
}

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    self.tview!.frame.size.width = 200
}

问题在于frame的{​​{1}}属性。文档说:

  

注意:注   frame属性不能直接设置动画。相反,您应该设置边界,anchorPoint和位置属性的适当组合的动画,以实现所需的结果。

如果你还没有解决你的问题,或者对于其他可能有问题的人,我希望这会有所帮助。