CAShapeLayer появляется перед просмотром - PullRequest
0 голосов
/ 19 марта 2019

У меня есть два представления, между которыми расположена линия изменяемого размера (просмотр с помощью 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 ]

1 голос
/ 19 марта 2019

Я думаю, что один из простых способов справиться с этим - это анимировать константу ограничения следующим образом:

  @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

0 голосов
/ 19 марта 2019

Есть пара проблем с вашим текущим кодом. В данный момент вы меняете путь без анимации, поэтому он обновляется немедленно. Также strokeEnd принимает значение от 0 до 1, поэтому сейчас ваш путь всегда имеет полный ход.

Вы должны анимировать изменение пути вместо штриха.

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: "path")
    animation.duration = 0.3
    animation.fromValue = dashedLayer.path
    animation.toValue = path
    dashedLayer.add(animation, forKey: "pathAnimation")
}
...