【问题标题】:Having custom CAShapeLayer animate with the Button使用 Button 自定义 CAShapeLayer 动画
【发布时间】:2016-03-29 08:55:13
【问题描述】:

我正在通过更改我的自动布局的约束并使用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")
}

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


自定义按钮:

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

【问题讨论】:

    标签: ios swift animation cashapelayer


    【解决方案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
    }
    

    问题在于CALayer is not animableframe 属性。文档说:

    注意:注意 frame 属性不能直接设置动画。相反,您应该对 bounds、anchorPoint 和 position 属性的适当组合进行动画处理,以实现所需的结果。

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

    【讨论】:

    • 它不工作。不过,我对隐式动画非常感兴趣,必须阅读并查看是否可以解决我的问题。
    • 你能发布你的整个自定义课程吗?尤其是添加图层的部分。
    • 你确定init 被调用了吗?行为是什么?您是否看到 border 图层但没有调整大小?根本看不到?
    • 这是我的另一个问题的链接,其中 GIF 显示了结果。我最后的 5 个问题都是关于(另一个)类似于这个问题的部分:stackoverflow.com/questions/36266312/…
    • 请注意,为了更清晰的代码,我已经简化了实际代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多