菜鸟教程小白 发表于 2022-12-11 18:38:31

ios - 以模态方式显示另一个 vc 时,CABasicAnimation 已完成


                                            <p><p>我使用下面的方式来暂停/恢复动画</p>

<pre><code>func pauseAnimation(){
var pausedTime = layer.convertTime(CACurrentMediaTime(), fromLayer: nil)
layer.speed = 0.0
layer.timeOffset = pausedTime
}

func resumeAnimation(){
var pausedTime = layer.timeOffset
layer.speed = 1.0
layer.timeOffset = 0.0
layer.beginTime = 0.0
let timeSincePause = layer.convertTime(CACurrentMediaTime(), fromLayer: nil) - pausedTime
layer.beginTime = timeSincePause
}
</code></pre>

<p>只要当前呈现 ViewController,它就可以发挥魅力。</p>

<p>当我以模态方式呈现另一个 ViewController 然后将其关闭时,无论在此呈现/关闭操作期间经过了多少时间,动画都会完成。</p>

<p>您对为什么会发生这种情况有什么建议吗?如何解决?我想补充一点,所有其他 View 都保持其状态,只有动画完成。</p>

<p>编辑:</p>

<p>我刚刚发现无论暂停/恢复都会发生这种情况 - 在这种情况下,正在进行的动画也会完成。</p>

<p>这是我展示动画实现的代码</p>

<pre><code>import Foundation

import UIKit

class CircleView: UIView {

var circleLayer: CAShapeLayer!

@IBOutlet var view: UIView!


@IBOutlet weak var progressLabel: UILabel!

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    Bundle.main.loadNibNamed(&#34;CircleView&#34;, owner: self, options: nil)
    self.addSubview(view)
    view.frame = self.bounds

}

override func awakeFromNib() {
      super.awakeFromNib()
      setupAppearance()

}

func setupAppearance() {
    progressLabel.textColor = UIColor.textColor
    progressLabel.font = UIFont.textTimerClock
}


func setup(progress:Double, clockwise:Bool) {

    self.backgroundColor = UIColor.clear
    var strokeColor = UIColor.positiveProgressColor
    if !clockwise { strokeColor = UIColor.positiveProgressColor }

    // Use UIBezierPath as an easy way to create the CGPath for the layer.
    // The path should be the entire circle.
    let circlePath = UIBezierPath(arcCenter: CGPoint(x: frame.size.width / 2.0, y: frame.size.height / 2.0), radius: (frame.size.width - 10)/2, startAngle: 0.0, endAngle: CGFloat(.pi * 2 * progress), clockwise: clockwise)

    // Setup the CAShapeLayer with the path, colors, and line width
    circleLayer = CAShapeLayer()
    circleLayer.path = circlePath.cgPath
    circleLayer.fillColor = UIColor.clear.cgColor
    circleLayer.strokeColor = strokeColor.cgColor
    circleLayer.lineWidth = 8.0;

    // Don&#39;t draw the circle initially
    circleLayer.strokeEnd = 0.0

    // Add the circleLayer to the view&#39;s layer&#39;s sublayers
    layer.addSublayer(circleLayer)

    //add grey path
    let greyCircleLayer = CAShapeLayer()

    let greyCirclePath = UIBezierPath(arcCenter: CGPoint(x: frame.size.width / 2.0, y: frame.size.height / 2.0), radius: (frame.size.width - 10)/2, startAngle: 0.0, endAngle: CGFloat(.pi * 2.0), clockwise: true)

    greyCircleLayer.path = greyCirclePath.cgPath
    greyCircleLayer.fillColor = UIColor.clear.cgColor
    greyCircleLayer.strokeColor = UIColor.appLightGrey.cgColor
    greyCircleLayer.lineWidth = 1.0;

    // Don&#39;t draw the circle initially
    circleLayer.strokeEnd = 0.0

    // Add the circleLayer to the view&#39;s layer&#39;s sublayers
    layer.insertSublayer(greyCircleLayer, below: circleLayer)
    if progressLabel != nil {

      progressLabel.text = &#34;10&#34;}
}

func pauseAnimation(){
    let pausedTime = circleLayer.convertTime(CACurrentMediaTime(), from: nil)
    circleLayer.speed = 0.0
    circleLayer.timeOffset = pausedTime
}

func resumeAnimation(){
    let pausedTime = circleLayer.timeOffset
    circleLayer.speed = 1.0
    circleLayer.timeOffset = 0.0
    circleLayer.beginTime = 0.0
    let timeSincePause = layer.convertTime(CACurrentMediaTime(), from: nil) - pausedTime
    circleLayer.beginTime = timeSincePause
}


func animateCircle(duration: TimeInterval, color: UIColor) {
    // We want to animate the strokeEnd property of the circleLayer
            circleLayer.strokeColor = color.cgColor
    let animation = CABasicAnimation(keyPath: &#34;strokeEnd&#34;)

    // Set the animation duration appropriately
    animation.duration = duration

    // Animate from 0 (no circle) to 1 (full circle)
    animation.fromValue = 0
    animation.toValue = 1

    // Do a linear animation (i.e. the speed of the animation stays the same)
    animation.timingFunction = CAMediaTimingFunction(name: kCAAnimationLinear)

    // Set the circleLayer&#39;s strokeEnd property to 1.0 now so that it&#39;s the
    // right value when the animation ends.
    circleLayer.strokeEnd = 1.0

    // Do the actual animation
    circleLayer.add(animation, forKey: &#34;animateCircle&#34;)
}
}
</code></pre>

<p>还有一点值得一提:init()、awakeFromNib() 没有被再次调用,所以情况并非如此。</p>

<p>另一个:推送 VC 而不是模态呈现也是如此。</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>通常,当您显示另一个 ViewController 时,当前 ViewController 的 View 会从窗口中移除。这也会从它们的图层中删除所有待处理的动画,并且任何现有的动画完成处理程序都会使用 <code>false</code> 调用,因为动画尚未完成(另见 <a href="https://stackoverflow.com/a/21200504/2352344" rel="noreferrer noopener nofollow">https://stackoverflow.com/a/21200504/2352344</a> )。</p>

<p>返回 ViewController 后要继续动画,你应该在<code>viewWillAppear</code>中重建动画对象。</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 以模态方式显示另一个 vc 时,CABasicAnimation 已完成,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/46096086/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/46096086/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 以模态方式显示另一个 vc 时,CABasicAnimation 已完成