ios - 使用按钮自定义 CAShapeLayer 动画

标签 ios swift animation cashapelayer

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

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")
}

没有任何效果,我已经苦苦挣扎了好几天..


自定义按钮:

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
    }
}

最佳答案

您所要做的就是在调整 View 的背衬层大小时也调整子层的大小。因为implicit animation变化应该是动画的。因此,您所需要做的基本上就是在自定义 View 类中设置它:

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
}

问题在于 CALayer 的 frame 属性不可设置动画。文档说:

Note:Note The frame property is not directly animatable. Instead you should animate the appropriate combination of the bounds, anchorPoint and position properties to achieve the desired result.

如果您尚未解决问题或其他可能遇到问题的人,我希望这会有所帮助。

关于ios - 使用按钮自定义 CAShapeLayer 动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36279640/

相关文章:

ios - 什么是正确的 IOS 正则表达式

ios - 为什么我不能从我的 Controller 添加到我的模型中的字典?

jquery - 侧边栏的错误折叠动画

android - 写入远程数据库操作可以在单独的异步线程中进行吗? (德尔福)

swift - "Missing required entitlement"用于 NFCTagReaderSession

ios - Firebase 快速返回 incored 快照

swift - 你能让一个类的所有对象通过一个方法调用做同样的事情吗?

javascript - 将边距应用于 Canvas 时,HTML5 Canvas 游戏将无法运行

c# - Wpf动画背景颜色

ios - iOS 中的接触点坐标未正确映射