OStack程序员社区-中国程序员成长平台

标题: ios - 以模态方式显示另一个 vc 时,CABasicAnimation 已完成 [打印本页]

作者: 菜鸟教程小白    时间: 2022-12-11 18:38
标题: ios - 以模态方式显示另一个 vc 时,CABasicAnimation 已完成

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

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
}

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

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

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

编辑:

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

这是我展示动画实现的代码

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("CircleView", 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(progressouble, 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't draw the circle initially
    circleLayer.strokeEnd = 0.0

    // Add the circleLayer to the view's layer'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't draw the circle initially
    circleLayer.strokeEnd = 0.0

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

        progressLabel.text = "10"}
}

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: "strokeEnd")

    // 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's strokeEnd property to 1.0 now so that it's the
    // right value when the animation ends.
    circleLayer.strokeEnd = 1.0

    // Do the actual animation
    circleLayer.add(animation, forKey: "animateCircle")
}
}

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

另一个:推送 VC 而不是模态呈现也是如此。



Best Answer-推荐答案


通常,当您显示另一个 View Controller 时,当前 View Controller 的 View 会从窗口中移除。这也会从它们的图层中删除所有待处理的动画,并且任何现有的动画完成处理程序都会使用 false 调用,因为动画尚未完成(另见 https://stackoverflow.com/a/21200504/2352344 )。

返回 View Controller 后要继续动画,你应该在viewWillAppear中重建动画对象。

关于ios - 以模态方式显示另一个 vc 时,CABasicAnimation 已完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46096086/






欢迎光临 OStack程序员社区-中国程序员成长平台 (https://ostack.cn/) Powered by Discuz! X3.4