Resuming drawing a CAShapeLayer when view reenters foreground?

60 views Asked by At
  func makeACircle(circle: UIView, stokeStart: Double, duration: Double){


        var progressCircle = CAShapeLayer();

        let centerPoint = CGPoint (x: circle.bounds.width / 2, y: circle.bounds.width / 2);
        let circleRadius : CGFloat = circle.bounds.width / 2

        var circlePath = UIBezierPath(arcCenter: centerPoint, radius: circleRadius, startAngle: CGFloat(-0.5 * M_PI), endAngle: CGFloat(1.5 * M_PI), clockwise: true    );

        progressCircle = CAShapeLayer ();
        progressCircle.path = circlePath.cgPath;
        progressCircle.strokeColor = UIColor.white.cgColor;
        progressCircle.fillColor = UIColor.clear.cgColor;
        progressCircle.lineWidth = 10;
        progressCircle.strokeStart = 0;
        progressCircle.strokeEnd = 1;
        progressCircle.borderWidth = 1
        progressCircle.borderColor = UIColor.black.cgColor

        circle.layer.addSublayer(progressCircle);
       // progressCircle.clipsToBounds = false
        self.view.addSubview(circle)

        let animation = CABasicAnimation(keyPath: "strokeEnd")

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

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

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

        // Set the circleLayer's strokeEnd property to 1.0 now so that it's the
        // right value when the animation ends.
        progressCircle.strokeEnd = 1.0

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

    }

I'm drawing circles in with the above code. It draws a circle around buttons on the screen that represent time that's passed since the creation of the button. This code works, but when I go to the homescreen and come back, all of the circles on the screen are completely filled in regardless of how much time was left. If within the app I then switch to another page and then come back, it fixes it.

I'm calling makeACircle from within this firebase query

 currentUserRef?.child("invitedToPosts").queryOrdered(byChild: "timestamp").queryStarting(atValue: cutoff).observe(.childAdded) { (snapshot: FIRDataSnapshot) in 

Once I have enough information about a button to be made, I make the button, then call the makeACircle.

Any ideas on how to prevent the circles from not appearing as if they've reached the strokeEnd when I load in from the homepage?

1

There are 1 answers

0
Rob On

When you pause the animation,

  • Look at the presentation layer and save its strokeEnd.

  • You need to stop the animation, do so. You may want to set the strokeEnd from the presentation layer's value to avoid any jarring changes.

  • See how much time has elapsed since you started the animation (e.g. compare CACurrentMediaTime() when you paused vs the value when you started the animation) in order to figure out how much time is remaining in the animation.

Then when you re-present the layer, you now have the fromValue for the strokeEnd and what the remaining duration is.

Another thing that can be useful is to set the delegate of the animation and then use animationDidStop to nil your "in progress" state variables if the animation successfully finishes (i.e. if finished is true).