CAShapeLayer出现在视图之前

时间:2019-03-19 10:15:35

标签: ios swift calayer cashapelayer cabasicanimation

我有两个视图,它们之间是可调整大小的行(使用CAShapeLayer的视图)。我面临的问题是,尽管动画在图层上,但它的显示速度要比视图更改的速度快。我知道图层的动画完全不同,但是无法理解我的错在哪里。请告诉我我做错了什么。

这是我图层动画的代码(也使用了“ strokeStart”,但没有用):

override func layoutSubviews() {
    super.layoutSubviews()
    let centerX = bounds.size.width / 2
    let path = CGMutablePath()
    path.addLines(between: [CGPoint(x: centerX, y: 0), CGPoint(x: centerX, y: frame.height)])
    dashedLayer.path = path
    dashedLayer.frame = bounds

    let animation = CABasicAnimation(keyPath: "strokeEnd")
    animation.fromValue = height
    animation.toValue = bounds.size.height
    height = bounds.size.height
    animation.duration = 0.3
    dashedLayer.add(animation, forKey: nil)
}

视图的动画代码(由于修改视图,我为layoutIfNeeded设置了动画):

UIView.animate(withDuration: 0.3, animations: {
    self.view.layoutIfNeeded()
    ...

2 个答案:

答案 0 :(得分:1)

我认为处理此问题的一种简单方法是为约束常量设置动画,如下所示:

  @IBOutlet weak  var heightConstraint: NSLayoutConstraint!

  UIView.animate(withDuration: 3, animations: {

        self. heightConstaint.constant = 300 // This constant is the height of top big view. 

        self.view.layoutIfNeeded()}

CAShapeLayer所在的另一种视图。我称之为line View。其高度应与top big view的高度相同。

line view中,您可以添加动画。这应该与您的实现类似。

   override func didMoveToSuperview() {
     super.didMoveToSuperview()
     dashedLayer.backgroundColor = UIColor.clear.cgColor
     layer.addSublayer(dashedLayer)
     height = bounds.size.height
   }

  override func layoutSubviews() {
    super.layoutSubviews()
    let centerX = bounds.size.width / 2
    let path = CGMutablePath()
    path.addLines(between: [CGPoint(x: centerX, y: 0), CGPoint(x: centerX, y: frame.height)])
    dashedLayer.path = path
    dashedLayer.lineWidth = 3.0
    dashedLayer.strokeColor = UIColor.blue.cgColor

    let animation = CABasicAnimation(keyPath: "strokeEnd")
    animation.fromValue = height / bounds.size.height
    animation.toValue = 1.0 
    animation.timingFunction = CAMediaTimingFunction.init(name: CAMediaTimingFunctionName.easeInEaseOut)
    height = bounds.size.height
    animation.duration = 3.0
    dashedLayer.add(animation, forKey: nil)
}

它在这里扩展。您可以修改代码以自己收缩。

enter image description here

以下是反转动画。

override func didMoveToSuperview() {
    super.didMoveToSuperview()
    dashedLayer.backgroundColor = UIColor.clear.cgColor
    layer.addSublayer(dashedLayer)
    height = bounds.size.height
      clipsToBounds = true
}


override func layoutSubviews() {
    super.layoutSubviews()
    let centerX = bounds.size.width / 2
    let path = CGMutablePath()
    path.addLines(between: [CGPoint(x: centerX, y: 0), CGPoint(x: centerX, y: max(height , bounds.size.height) )])
    dashedLayer.path = path
    dashedLayer.lineWidth = 3.0
    dashedLayer.strokeColor = UIColor.blue.cgColor

    let animation = CABasicAnimation(keyPath: "strokeEnd")

    if (height < bounds.size.height){
    animation.fromValue = height / bounds.size.height
        animation.toValue = 1.0}

    else {
        animation.fromValue = 1.0
        animation.toValue = bounds.size.height / height}


    animation.timingFunction = CAMediaTimingFunction.init(name: CAMediaTimingFunctionName.easeInEaseOut)
    height = bounds.size.height
    animation.duration = 3
    dashedLayer.add(animation, forKey: nil)
}

enter image description here

答案 1 :(得分:0)

您当前的代码有两个问题。目前,您正在更改没有动画的路径,因此它会立即更新。 strokeEnd的值也为0到1,因此现在您的路径始终具有完整的笔触。 您应该为路径更改而不是笔触设置动画。 覆盖func layoutSubviews(){     super.layoutSubviews()     让centerX = bounds.size.width / 2     让路径= CGMutablePath()     path.addLines(介于:[CGPoint(x:centerX,y:0),CGPoint(x:centerX,y:frame.height)])     dashedLayer.path =路径     dashedLayer.frame =界限     让animation = CABasicAnimation(keyPath:“路径”)     animation.duration = 0.3     animation.fromValue = dashedLayer.path     animation.toValue =路径     dashedLayer.add(animation,forKey:“ pathAnimation”) }