UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Circular Progress Bar - Animate progress change

Forums > iOS

Hi, I am trying to make custom circular progress bar. So far, I can animate progress filling status from 0 to some value (lets say 30), but when the value is changed (lets say to 60) I dont want progress status to be animated from 0 to 60, but from 30 to 60.

Here is my animation code - I'm actually adding another sublayer to the original one...

    private var progressLayer = CAShapeLayer()
    private var progressValue: Int = 0;

    ///
    func updateProgressPath() {
        let progressValueRadians = startPoint + CGFloat(progressValue) * 3.6 * CGFloat.pi/180.0
        let progressPath = UIBezierPath(arcCenter: CGPoint(x: frame.size.width / 2.0, y: frame.size.height / 2.0), radius: radius, startAngle: startPoint, endAngle: progressValueRadians, clockwise: true)

        // progressLayer path defined to circularPath
        progressLayer.path = progressPath.cgPath
        // ui edits
        progressLayer.fillColor = UIColor.clear.cgColor
        progressLayer.lineCap = .butt
        progressLayer.lineWidth = radius * barWidthPercentage
        progressLayer.strokeEnd = 0
        progressLayer.strokeColor = progressBarColorDone
        // added progressLayer to layer
        layer.addSublayer(progressLayer)
    }

    ///
    func progressAnimation(duration: TimeInterval) {
        // created circularProgressAnimation with keyPath
        let circularProgressAnimation = CABasicAnimation(keyPath: "strokeEnd")
        // set the end time
        circularProgressAnimation.duration = duration
        circularProgressAnimation.toValue = 1.0
        circularProgressAnimation.fillMode = .forwards
        circularProgressAnimation.isRemovedOnCompletion = false
        progressLayer.add(circularProgressAnimation, forKey: "progressAnim")
    }

    ///
    func setValue(to value: Int) {
        if value > 100 || value < 0 {
            progressValue = 0
            return
        }
        progressValue = value
        updateProgressPath()
        progressAnimation(duration: 1)
    }

4      

Hi iLomidze

If you doing this in SwiftUI. You can do this

struct ProgressRing: View {
    @Binding var progress: Double

    private var formattedPercent: String {
        let formatter = NumberFormatter()
        formatter.maximumFractionDigits = 1
        formatter.numberStyle = .percent
        return formatter.string(from: NSNumber(value: progress)) ?? ""
    }

    var body: some View {
        ZStack {
            Circle()
                .stroke(Color.black, lineWidth: 24)

            Text(formattedPercent)
                .font(.system(size: 64))

            Circle()
                .trim(from: 0.0, to: CGFloat(progress))
                .stroke(Color.blue, style: StrokeStyle(lineWidth: 13, lineCap: .round))
                .rotationEffect(.degrees(-90))
        }
        .padding(30)
        .onTapGesture {
            withAnimation {
                progress = min(1.0, progress + 0.125)
            }
        }
    }
}

then can use it in the view

struct ContentView: View {
    @State var progress: Double = 0.25

    private var formattedPercent: String {
        let formatter = NumberFormatter()
        formatter.maximumFractionDigits = 1
        formatter.numberStyle = .percent
        return formatter.string(from: NSNumber(value: progress)) ?? ""
    }

    var body: some View {
        VStack {
            Slider(value: $progress)
                .padding()
            ProgressRing(progress: $progress)
                .frame(width: 300, height: 300)
        }
    }
}

4      

TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and free gifts!

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.