Reputation: 493
How to do I implement a horizontal progress bar in iOS like as Android.
I have tried the following, and found a solution like deteminate.
func startSendPickUpRequestShakeTimer () {
if self.movingViewTimer == nil {
self.movingViewTimer = Timer.scheduledTimer(
timeInterval: TimeInterval(movingViewSpeed),
target : self,
selector : #selector(self.startAnimating),
userInfo : nil,
repeats : true)
}
}
func startAnimating() {
let movingViewX = movingView.frame.minX >= view.frame.maxX ? 0-movingView.frame.width-forwardX:movingView.frame.minX + forwardX
self.movingView.frame = CGRect(x: movingViewX, y: movingView.frame.minY, width: movingView.frame.width, height: moviewViewHeight)
}
But how can I implement the others, or is there any good resource to do that?
Upvotes: 16
Views: 13966
Reputation: 1028
I added this extension to UIProgressBar that animates a 40pt wide bar from left to right and back
extension UIProgressView {
func startAnimateIndeterminate() {
// When bar exists, it's animating
guard indeterminateAnimationBar == nil else { return }
let width = 40.0
let animationDuration = 1.0
let endPos = bounds.width-width
// `UIProgressView` contains two image views, the background and the animation bar which is the last.
// The animation bar has a cap resizable image which is pulled from here and inserted into an own bar
// instance that can be managed independently.
guard let original = self.subviews.filter({ $0 is UIImageView }).last as? UIImageView else { return }
let bar = UIImageView(image: original.image)
bar.restorationIdentifier = "IndeterminateBar"
bar.frame = CGRect(origin: .zero, size: .init(width: width, height: bounds.height))
addSubview(bar)
func animate() {
UIView.animate(withDuration: animationDuration, animations: {
bar.frame.origin.x = endPos
}, completion: { [weak self] _ in
if self?.indeterminateAnimationBar == nil { return }
UIView.animate(withDuration: animationDuration, animations: {
bar.frame.origin.x = 0
}, completion: { [weak self] _ in
if self?.indeterminateAnimationBar == nil { return }
animate() // Repeat animation
})
})
}
animate()
}
func stopAnimateIndeterminate() {
// When bar exists, it's animating. Then remove from superView which will also stop the animation.
guard let bar = indeterminateAnimationBar else { return }
bar.removeFromSuperview()
}
var indeterminateAnimationBar: UIImageView? {
subviews.filter { $0 is UIImageView && $0.restorationIdentifier == "IndeterminateBar" }.last as? UIImageView
}
}
Upvotes: 0
Reputation: 795
I had coded this extension for indetermined progress in ios. Maybe this can help
extension UIProgressView{
private struct Holder {
static var _progressFull:Bool = false
static var _completeLoading:Bool = false;
}
var progressFull:Bool {
get {
return Holder._progressFull
}
set(newValue) {
Holder._progressFull = newValue
}
}
var completeLoading:Bool {
get {
return Holder._completeLoading
}
set(newValue) {
Holder._completeLoading = newValue
}
}
func animateProgress(){
if(completeLoading){
return
}
UIView.animate(withDuration: 1, animations: {
self.setProgress(self.progressFull ? 1.0 : 0.0, animated: true)
})
progressFull = !progressFull;
DispatchQueue.main.asyncAfter(deadline: .now() + 1.2) {
self.animateProgress();
}
}
func startIndefinateProgress(){
isHidden = false
completeLoading = false
animateProgress()
}
func stopIndefinateProgress(){
completeLoading = true
isHidden = true
}
}
Fiverr: https://www.fiverr.com/kamranbashir
Upvotes: 5
Reputation: 2979
This is now part of Material components for iOS. https://material.io/develop/ios/components/progress-indicators/progress-views
pod 'MaterialComponents/ProgressView'
import MaterialComponents.MaterialProgressView
Code sample:
let progressView = MDCProgressView()
progressView.mode = .indeterminate
progressView.progressTintColor = .white
progressView.trackTintColor = UIColor.white.withAlphaComponent(0.2)
progressView.startAnimating()
view.addSubview(progressView)
//Then set constraints for your view (I used SnapKit https://github.com/SnapKit/SnapKit)
progressView.snp.makeConstraints { (make) in
make.left.equalTo(header.snp.left)
make.right.equalTo(header.snp.right)
make.top.equalTo(header.snp.bottom).offset(20)
make.height.equalTo(4)
}
Upvotes: 0