Search code examples
iosanimationswift3uibezierpathcashapelayer

Animation in swift : Circular Dashed Loading Bar?


I have literally looked over the web for like 2to3 hours, unfortunately couldn't find anything, (2nd problem: being new to swift ->this can be ignored)

Basically I need Circular dashed Loading bar : Every dot should animate Individually like a circular load..

I was able to make a circular dashed circle but couldn't animate it...

Any help would be appreciated even if thats an library from github or anything..

Here's my code for creating a circular dashed circle..

import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
    }

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(true)
    let circlePath = UIBezierPath(arcCenter: CGPoint(x: 100,y: 100), radius: 100.0, startAngle: 0.0, endAngle:CGFloat(M_PI * 2), clockwise: true)
    let shapeLayer = CAShapeLayer()
    shapeLayer.path = circlePath.cgPath
    shapeLayer.position = CGPoint(x: 100, y: 100)
    shapeLayer.fillColor = UIColor.clear.cgColor
    shapeLayer.strokeColor = UIColor.blue.cgColor
    shapeLayer.lineWidth = 6.0
    let one : NSNumber = 1
    let two : NSNumber = 13
    shapeLayer.lineDashPattern = [one,two]
    shapeLayer.lineCap = kCALineCapRound
    view.layer.addSublayer(shapeLayer)

}
override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning()}
}

thats what I got

This is what I want (Below One):

enter image description here


Solution

  • I have been playing around with custom activity indicators, so here's one way to do it

    import UIKit
    
    @IBDesignable class ActivityIndicatorCircle: UIView {
        var  timerInterval: Double   = 0.1
        var timer : Timer?
        var endAngle: CGFloat   = 0.0
        var angleStep           = CGFloat.pi / 20.0
        var angleOffset         = -CGFloat.pi / 2.0
    
        var shapeLayer = CAShapeLayer()
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
    
        override init(frame: CGRect) {
            super.init(frame: frame)
        }
    
        func startAnimating() {
            superview?.bringSubview(toFront: self)
    
            layer.cornerRadius = frame.width / 2
            self.clipsToBounds = true
    
            isHidden = false
            timer?.invalidate()
            timer = nil
    
            timer = Timer.scheduledTimer(timeInterval: timerInterval,
                                     target: self,
                                     selector: #selector(self.updateCircle),
                                     userInfo: nil,
                                     repeats: true)
        }
    
        func stopAnimating() {
            isHidden = true
            timer?.invalidate()
            timer = nil
        }
    
        func updateCircle() {
            endAngle += angleStep
            if endAngle > CGFloat.pi * 2.0 {
                endAngle -= CGFloat.pi * 2.0
            }
            DispatchQueue.main.async {
                self.shapeLayer.removeFromSuperlayer() // remove the previous version
    
                let lineWidth: CGFloat = 6.0
                let radius = self.frame.size.width / 2.0 // if the view is square, this gives us center as well
    
                let circlePath = UIBezierPath(arcCenter: CGPoint(x: radius,y: radius), radius: radius - lineWidth, startAngle: self.angleOffset, endAngle: self.endAngle + self.angleOffset, clockwise: true)
    
                self.shapeLayer.path = circlePath.cgPath
                self.shapeLayer.position = CGPoint(x: 0, y: 0)
                self.shapeLayer.fillColor = UIColor.clear.cgColor
                self.shapeLayer.strokeColor = UIColor.blue.cgColor
                self.shapeLayer.lineWidth = lineWidth
                let one : NSNumber = 1
                let two : NSNumber = 13
                self.shapeLayer.lineDashPattern = [one,two]
                self.shapeLayer.lineCap = kCALineCapRound
                self.layer.addSublayer(self.shapeLayer)
            }
        }
    }
    

    to use this, add a UIView to your storyboard, and set the class to ActivityIndicatorCircle

    To start it, call activityIndicatorCircle.startAnimating()