I'm trying to create a Custom Progress Bar View and the idea is to have a timer that will update every second. However, the transition from the progress is not so smooth.
If I reduce the timer interval to something like 0.01 instead of 0.1 the "animation" works nicely; however, I'm trying to avoid it.
There's some way to make this animation smooth using 1 second on the Timer interval?
class CustomProgressBar: UIView {
private let progressLayer = CALayer()
var progress: CGFloat = 1.0 {
didSet {
setNeedsDisplay()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
addSublayers()
startTimer()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
addSublayers()
startTimer()
}
private func startTimer() {
Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateProgressBar), userInfo: nil, repeats: true)
}
override func draw(_ rect: CGRect) {
let backgroundMask = CAShapeLayer()
backgroundMask.path = UIBezierPath(roundedRect: rect, cornerRadius: rect.height * 0.5).cgPath
layer.mask = backgroundMask
updateLayer(rect: rect, color: .white)
backgroundColor = .black
progressLayer.backgroundColor = UIColor.white.cgColor
}
private func addSublayers() {
layer.addSublayer(progressLayer)
}
@objc func updateProgressBar() {
progress -= 0.1
}
private func updateLayer(rect: CGRect, color: UIColor?) {
let progressRectBorderSize = rect.height * 0.2
let width: CGFloat
width = max(rect.width * progress - (progressRectBorderSize * 2), 0)
let progressRect = CGRect(origin: CGPoint(x: progressRectBorderSize, y: progressRectBorderSize), size: CGSize(width: width, height: rect.height - (progressRectBorderSize * 2)))
let progressBackgroundMask = CAShapeLayer()
let progressBackgroundMaskRoundedRect = CGRect(x: 0, y: 0, width: progressRect.width, height: progressRect.height)
progressBackgroundMask.path = UIBezierPath(roundedRect: progressBackgroundMaskRoundedRect, cornerRadius: progressRect.height * 0.5).cgPath
progressLayer.mask = progressBackgroundMask
progressLayer.frame = progressRect
}
}