Remove UIBezierPath with animation which added earlier

70 views Asked by At

In my UICollectionViewCell, I've added a border via UIBezierPath with animation which is as below.

class AnimalSelectionCollectionCell: UICollectionViewCell {
    ...
    let shapeLayer: CAShapeLayer = CAShapeLayer()
    override func layoutSubviews() {
        super.layoutSubviews()
        let path: UIBezierPath = UIBezierPath(
            roundedRect: contentView.bounds.inset(by: UIEdgeInsets(top: 2, left: 2, bottom: 2, right: 2)),
            byRoundingCorners: .allCorners, cornerRadii: CGSize(width: contentView.bounds.size.width, height: 0.0))
        shapeLayer.path = path.cgPath
    }

    func setData() {
        ...
        shapeLayer.lineWidth = 1.0
        shapeLayer.fillColor = UIColor.clear.cgColor
        contentView.layer.addSublayer(shapeLayer)
    }

    func startAnimation() {
        shapeLayer.strokeColor = AppColors.Text.selectedName.cgColor

        let animation: CABasicAnimation = CABasicAnimation(keyPath: "strokeEnd")
        animation.fromValue = 0.0
        animation.toValue = 1.0
        animation.duration = 0.5

        shapeLayer.add(animation, forKey: "myStroke")
    }
}

On selection of UICollectionViewCell I'm calling startAnimation() method which draw border with animation. Now, on on select again I want to remove that border with animation on reverse order (i.e. from 1.0 to 0.0).

How can I remove drawn path with animation?

1

There are 1 answers

1
Sweeper On

Assuming allowsMultipleSelection is true, you can check isSelected and do different things depending on it:

func startAnimation() {
    if isSelected {
        showDeselectionAnimation()
    } else {
        showSelectionAnimation()
    }
}

Also consider overriding isSelected and putting this logic in its didSet, instead of having a startAnimation function. isSelected would be automatically set by UIKit.

Then, put your original code to show the selection animation in showSelectionAnimation. For the deselection animation, do something similar, but reverse fromValue and toValue. At the end of the animation, you should also set the stroke color back to clear, so that everything is back to the state before you called showSelectionAnimation.

func showDeselectionAnimation() {
    let animation: CABasicAnimation = CABasicAnimation(keyPath: "strokeEnd")
    animation.fromValue = 1.0
    animation.toValue = 0.0
    animation.duration = 0.5
    animation.delegate = self
    shapeLayer.add(animation)
}

...

func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
    shapeLayer.strokeColor = UIColor.clear.cgColor
}