Swift动画循环进度条

问题描述 投票:0回答:1

我已经在Swift中创建了一个循环进度条,当用户按住视图时,它会动画超过1.5秒,达到值1。但是我希望在动画完成时添加一个新的viewcontroller,如果用户提前结束,则重新启动我的循环进度条。有人能帮我吗?

当用户按住视图并在发布时停止时,循环进度条正在处理动画。

class CounterView: UIView {
    var bgPath: UIBezierPath!
    var shapeLayer: CAShapeLayer!
    var progressLayer: CAShapeLayer!


    override init(frame: CGRect) {
        super.init(frame: frame)
        bgPath = UIBezierPath()
        self.simpleShape()
    }

    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        bgPath = UIBezierPath()
        self.simpleShape()
    }

    func simpleShape()
    {
        createCirclePath()
        shapeLayer = CAShapeLayer()
        shapeLayer.path = bgPath.cgPath
        shapeLayer.lineWidth = 5
        shapeLayer.fillColor = nil
        shapeLayer.strokeColor = UIColor.clear.cgColor

        progressLayer = CAShapeLayer()
        progressLayer.path = bgPath.cgPath
        progressLayer.lineCap = kCALineCapRound
        progressLayer.lineWidth = 5
        progressLayer.fillColor = nil
        progressLayer.strokeColor = UIColor.yellow.cgColor
        progressLayer.strokeEnd = 0.0


        self.layer.addSublayer(shapeLayer)
        self.layer.addSublayer(progressLayer)
    }

    private func createCirclePath()
    {

        let x = self.frame.width/2
        let y = self.frame.height/2
        let center = CGPoint(x: x, y: y)
        print(x,y,center)
        bgPath.addArc(withCenter: center, radius: x/CGFloat(2), startAngle: CGFloat(0), endAngle: CGFloat(6.28), clockwise: true)
        bgPath.close()
    }

    var animationCompletedCallback: ((_ isAnimationCompleted: Bool) -> Void)?

    func setProgressWithAnimation(duration: TimeInterval, value: Float)  {

        CATransaction.setCompletionBlock {
            if let callBack = self.animationCompletedCallback { callBack(true) }

        }

        CATransaction.begin()
        let  animation = CABasicAnimation (keyPath: "strokeEnd")
        animation.duration = duration
        animation.fromValue = 0
        animation.toValue = value
        animation.repeatCount = 1
        animation.timingFunction = CAMediaTimingFunction (name: kCAMediaTimingFunctionLinear)
        progressLayer.strokeEnd = CGFloat(value)
        progressLayer.add(animation, forKey: "animateprogress")

        CATransaction.commit()
}

    func removeLayers() {
        shapeLayer.removeAllAnimations()
        shapeLayer.removeFromSuperlayer()
        progressLayer.removeAllAnimations()
        progressLayer.removeFromSuperlayer()
    }





}





             class ViewController: UIViewController {


                    @IBOutlet weak var counterView: CounterView!
                    @IBOutlet weak var holdView: UIView!
                    var isAnimationCompleted = false             


                    override func viewDidLoad() {
                        super.viewDidLoad()
                        addLongPressGesture()
                       addCounterViewCallback()


                    }    
             @objc func longPress(gesture: UILongPressGestureRecognizer) {
        if gesture.state == UIGestureRecognizerState.began {
       // self.counterView.simpleShape()
        self.counterView.setProgressWithAnimation(duration: 1.5, value: 1.0)

        }
        if gesture.state == UIGestureRecognizerState.ended {
            if !isAnimationCompleted {
                self.counterView.removeLayers()
            }
        }
    }


    func addLongPressGesture(){
        let lpgr = UILongPressGestureRecognizer(target: self, action: #selector(longPress(gesture:)))
        lpgr.minimumPressDuration = 0
        self.holdView.addGestureRecognizer(lpgr)
    }

    private func addCounterViewCallback() {
        counterView.animationCompletedCallback = { [weak self] (isCompleted) in
            guard let weakSelf = self else {return}
            weakSelf.isAnimationCompleted = isCompleted
            weakSelf.addFlashView()
        }
    }


          func addFlashView(){
                        let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)

                        let resultViewController = storyBoard.instantiateViewController(withIdentifier: "ResultView") as! Flash

                        self.present(resultViewController, animated:true, completion:nil)
                    }

完成动画后添加新的viewcontroller,如果用户释放视图并再次按住它,则重新启动动画。

swift animation progress
1个回答
0
投票

添加callback以了解动画何时结束。并使用CATransaction知道动画何时完成。

var animationCompletedCallback: (() -> Void)?
func setProgressWithAnimation(duration: TimeInterval, value: Float)  {

    CATransaction.setCompletionBlock {
        if let callBack = animationCompletedCallback {
            callBack()
        }
    }

    CATransaction.begin()


    let  animation = CABasicAnimation (keyPath: "strokeEnd")
    animation.duration = duration
    animation.fromValue = 0
    animation.toValue = value
    animation.repeatCount = .infinity
    animation.timingFunction = CAMediaTimingFunction (name: kCAMediaTimingFunctionLinear)
    progressLayer.strokeEnd = CGFloat(value)
    progressLayer.add(animation, forKey: "animateprogress")

    CATransaction.commit()
}

并在addLongPressGesture()中的viewDidLoad()之后添加此函数:

private func addCounterViewCallback() {
    counterView.animationCompletedCallback = { [weak self] in
        guard let weakSelf = self else {return}
        weakSelf.addFlashView()
    }
}

要删除图层,请使用此:

func removeLayers() {
   shapeLayer.removeAllAnimations()
   shapeLayer.removeFromSuperlayer()
   progressLayer.removeAllAnimations()
   progressLayer.removeFromSuperlayer()
}

更新1:

要在用户停止按下时删除动画,您需要在回调中添加变量,如下所示:

var animationCompletedCallback: ((isAnimationCompleted: Bool) -> Void)?

所以现在CounterView的回调将是:

if let callBack = animationCompletedCallback { callBack(true) }

在你的控制器中添加一个变量:var isAnimationCompleted = false

改变addCounterViewCallback()

private func addCounterViewCallback() {
    counterView.animationCompletedCallback = { [weak self] (isCompleted) in
        guard let weakSelf = self else {return}
        weakSelf.isAnimationCompleted = isCompleted
        weakSelf.addFlashView()
    }
}

现在您可以在longPress()中添加一个条件:

if gesture.state == UIGestureRecognizerState.ended {
  if !isAnimationCompleted { 
      //Call remove layers code
  }
}

更新2:

CounterView中添加变量:

var isAnimationCompleted = true

像这样改变回调:

CATransaction.setCompletionBlock {
    if let callBack = self.animationCompletedCallback { callBack(isAnimationCompleted) }
}

在控制器longPress()

if gesture.state == UIGestureRecognizerState.ended {
   if !isAnimationCompleted {
      self.counterView.isAnimationCompleted = false
      self.counterView.removeLayers()
   }
}

addCounterViewCallback()修改为:

private func addCounterViewCallback() {
        counterView.animationCompletedCallback = { [weak self] (isCompleted) in
        guard let weakSelf = self else {return}
        weakSelf.isAnimationCompleted = isCompleted
        if isCompleted {
          weakSelf.addFlashView()
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.