diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2c22487 --- /dev/null +++ b/.gitignore @@ -0,0 +1,65 @@ +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData/ + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ + +## Other +*.moved-aside +*.xcuserstate + +## Obj-C/Swift specific +*.hmap +*.ipa +*.dSYM.zip +*.dSYM + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +.build/ + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots +fastlane/test_output diff --git a/LinearProgressBar.xcodeproj/project.pbxproj b/LinearProgressBar.xcodeproj/project.pbxproj index 9eb3f3b..ea9393f 100644 --- a/LinearProgressBar.xcodeproj/project.pbxproj +++ b/LinearProgressBar.xcodeproj/project.pbxproj @@ -12,7 +12,7 @@ 3721E0741DA78F1100DC9E8F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3721E0721DA78F1100DC9E8F /* Main.storyboard */; }; 3721E0761DA78F1100DC9E8F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3721E0751DA78F1100DC9E8F /* Assets.xcassets */; }; 3721E0791DA78F1100DC9E8F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3721E0771DA78F1100DC9E8F /* LaunchScreen.storyboard */; }; - 3721E0821DA78FA500DC9E8F /* LinearProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3721E0811DA78FA500DC9E8F /* LinearProgressBar.swift */; }; + 6AD200AF1DBBEE77007DA1A4 /* LinearProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD200AD1DBBED76007DA1A4 /* LinearProgressBar.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -23,7 +23,7 @@ 3721E0751DA78F1100DC9E8F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 3721E0781DA78F1100DC9E8F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 3721E07A1DA78F1100DC9E8F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 3721E0811DA78FA500DC9E8F /* LinearProgressBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LinearProgressBar.swift; sourceTree = ""; }; + 6AD200AD1DBBED76007DA1A4 /* LinearProgressBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LinearProgressBar.swift; path = Pod/Classes/LinearProgressBar.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -56,7 +56,7 @@ 3721E06D1DA78F1100DC9E8F /* LinearProgressBar */ = { isa = PBXGroup; children = ( - 3721E0801DA78F9C00DC9E8F /* Lib */, + 6AD200AD1DBBED76007DA1A4 /* LinearProgressBar.swift */, 3721E06E1DA78F1100DC9E8F /* AppDelegate.swift */, 3721E0701DA78F1100DC9E8F /* ViewController.swift */, 3721E0721DA78F1100DC9E8F /* Main.storyboard */, @@ -67,14 +67,6 @@ path = LinearProgressBar; sourceTree = ""; }; - 3721E0801DA78F9C00DC9E8F /* Lib */ = { - isa = PBXGroup; - children = ( - 3721E0811DA78FA500DC9E8F /* LinearProgressBar.swift */, - ); - name = Lib; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -150,7 +142,7 @@ files = ( 3721E0711DA78F1100DC9E8F /* ViewController.swift in Sources */, 3721E06F1DA78F1100DC9E8F /* AppDelegate.swift in Sources */, - 3721E0821DA78FA500DC9E8F /* LinearProgressBar.swift in Sources */, + 6AD200AF1DBBEE77007DA1A4 /* LinearProgressBar.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -314,6 +306,7 @@ 3721E07F1DA78F1100DC9E8F /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/LinearProgressBar.xcodeproj/project.xcworkspace/xcuserdata/Philippe.xcuserdatad/UserInterfaceState.xcuserstate b/LinearProgressBar.xcodeproj/project.xcworkspace/xcuserdata/Philippe.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100644 index b4e89de..0000000 Binary files a/LinearProgressBar.xcodeproj/project.xcworkspace/xcuserdata/Philippe.xcuserdatad/UserInterfaceState.xcuserstate and /dev/null differ diff --git a/LinearProgressBar.xcodeproj/xcuserdata/iosdev.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/LinearProgressBar.xcodeproj/xcuserdata/iosdev.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..b7f7d03 --- /dev/null +++ b/LinearProgressBar.xcodeproj/xcuserdata/iosdev.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,19 @@ + + + + + + + + + + + diff --git a/LinearProgressBar.xcodeproj/xcuserdata/iosdev.xcuserdatad/xcschemes/LinearProgressBar.xcscheme b/LinearProgressBar.xcodeproj/xcuserdata/iosdev.xcuserdatad/xcschemes/LinearProgressBar.xcscheme new file mode 100644 index 0000000..6d39519 --- /dev/null +++ b/LinearProgressBar.xcodeproj/xcuserdata/iosdev.xcuserdatad/xcschemes/LinearProgressBar.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LinearProgressBar.xcodeproj/xcuserdata/iosdev.xcuserdatad/xcschemes/xcschememanagement.plist b/LinearProgressBar.xcodeproj/xcuserdata/iosdev.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..2d630f2 --- /dev/null +++ b/LinearProgressBar.xcodeproj/xcuserdata/iosdev.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + LinearProgressBar.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 3721E06A1DA78F1100DC9E8F + + primary + + + + + diff --git a/LinearProgressBar/Base.lproj/Main.storyboard b/LinearProgressBar/Base.lproj/Main.storyboard index bb8673b..bf639cf 100644 --- a/LinearProgressBar/Base.lproj/Main.storyboard +++ b/LinearProgressBar/Base.lproj/Main.storyboard @@ -1,10 +1,8 @@ - - + + - - @@ -20,57 +18,63 @@ - - - - - + - - - - - - - - - - - - - - + + + + + + + + + - + - - - diff --git a/LinearProgressBar/LinearProgressBar.swift b/LinearProgressBar/LinearProgressBar.swift deleted file mode 100644 index 4d0ffa4..0000000 --- a/LinearProgressBar/LinearProgressBar.swift +++ /dev/null @@ -1,153 +0,0 @@ -// -// LinearProgressBar.swift -// CookMinute -// -// Created by Philippe Boisney on 18/11/2015. -// Copyright © 2015 CookMinute. All rights reserved. -// -// Google Guidelines: https://www.google.com/design/spec/components/progress-activity.html#progress-activity-types-of-indicators -// - -import UIKit - -open class LinearProgressBar: UIView { - - //FOR DATA - fileprivate var screenSize: CGRect = UIScreen.main.bounds - fileprivate var isAnimationRunning = false - - //FOR DESIGN - fileprivate var progressBarIndicator: UIView! - - //PUBLIC VARS - open var backgroundProgressBarColor: UIColor = UIColor(red:0.73, green:0.87, blue:0.98, alpha:1.0) - open var progressBarColor: UIColor = UIColor(red:0.12, green:0.53, blue:0.90, alpha:1.0) - open var heightForLinearBar: CGFloat = 5 - open var widthForLinearBar: CGFloat = 0 - - public init () { - super.init(frame: CGRect(origin: CGPoint(x: 0,y :20), size: CGSize(width: screenSize.width, height: 0))) - self.progressBarIndicator = UIView(frame: CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: 0, height: heightForLinearBar))) - } - - override public init(frame: CGRect) { - super.init(frame: frame) - self.progressBarIndicator = UIView(frame: CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: 0, height: heightForLinearBar))) - } - - required public init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - //MARK: LIFE OF VIEW - override open func layoutSubviews() { - super.layoutSubviews() - self.screenSize = UIScreen.main.bounds - - if widthForLinearBar == 0 || widthForLinearBar == self.screenSize.height { - widthForLinearBar = self.screenSize.width - } - - if (UIDeviceOrientationIsLandscape(UIDevice.current.orientation)) { - self.frame = CGRect(origin: CGPoint(x: self.frame.origin.x,y :self.frame.origin.y), size: CGSize(width: widthForLinearBar, height: self.frame.height)) - } - - if (UIDeviceOrientationIsPortrait(UIDevice.current.orientation)) { - self.frame = CGRect(origin: CGPoint(x: self.frame.origin.x,y :self.frame.origin.y), size: CGSize(width: widthForLinearBar, height: self.frame.height)) - } - } - - //MARK: PUBLIC FUNCTIONS ------------------------------------------------------------------------------------------ - - //Start the animation - open func startAnimation(){ - - self.configureColors() - - self.show() - - if !isAnimationRunning { - self.isAnimationRunning = true - - UIView.animate(withDuration: 0.5, delay:0, options: [], animations: { - self.frame = CGRect(x: 0, y: self.frame.origin.y, width: self.widthForLinearBar, height: self.heightForLinearBar) - }, completion: { animationFinished in - self.addSubview(self.progressBarIndicator) - self.configureAnimation() - }) - } - } - - //Start the animation - open func stopAnimation() { - - self.isAnimationRunning = false - - UIView.animate(withDuration: 0.5, animations: { - self.progressBarIndicator.frame = CGRect(x: 0, y: 0, width: self.widthForLinearBar, height: 0) - self.frame = CGRect(x: 0, y: self.frame.origin.y, width: self.widthForLinearBar, height: 0) - }) - } - - //MARK: PRIVATE FUNCTIONS ------------------------------------------------------------------------------------------ - - fileprivate func show() { - - // Only show once - if self.superview != nil { - return - } - - // Find current top viewcontroller - if let topController = getTopViewController() { - let superView: UIView = topController.view - superView.addSubview(self) - } - } - - fileprivate func configureColors(){ - - self.backgroundColor = self.backgroundProgressBarColor - self.progressBarIndicator.backgroundColor = self.progressBarColor - self.layoutIfNeeded() - } - - fileprivate func configureAnimation() { - - guard let superview = self.superview else { - stopAnimation() - return - } - - self.progressBarIndicator.frame = CGRect(origin: CGPoint(x: 0, y :0), size: CGSize(width: 0, height: heightForLinearBar)) - - UIView.animateKeyframes(withDuration: 1.0, delay: 0, options: [], animations: { - - UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.5, animations: { - self.progressBarIndicator.frame = CGRect(x: 0, y: 0, width: self.widthForLinearBar*0.7, height: self.heightForLinearBar) - }) - - UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.5, animations: { - self.progressBarIndicator.frame = CGRect(x: superview.frame.width, y: 0, width: 0, height: self.heightForLinearBar) - - }) - - }) { (completed) in - if (self.isAnimationRunning){ - self.configureAnimation() - } - } - } - - // ----------------------------------------------------- - //MARK: UTILS --------------------------------------- - // ----------------------------------------------------- - - fileprivate func getTopViewController() -> UIViewController? { - var topController: UIViewController? = UIApplication.shared.keyWindow?.rootViewController - while topController?.presentedViewController != nil { - topController = topController?.presentedViewController - } - return topController - } -} diff --git a/LinearProgressBar/ViewController.swift b/LinearProgressBar/ViewController.swift index 6f4d358..99226dd 100644 --- a/LinearProgressBar/ViewController.swift +++ b/LinearProgressBar/ViewController.swift @@ -10,31 +10,45 @@ import UIKit class ViewController: UIViewController { - let linearBar: LinearProgressBar = LinearProgressBar() + var linearBar: LinearProgressBar = { + + var bar = LinearProgressBar(frame: CGRect(x: 10, y: UIScreen.main.bounds.height - 200, width: UIScreen.main.bounds.width - 20, height: 5)) + + bar.backgroundColor = UIColor(red:0.68, green:0.81, blue:0.72, alpha:1.0) + bar.progressBarColor = UIColor(red:0.26, green:0.65, blue:0.45, alpha:1.0) + bar.widthRatioOffset = 0.78 + bar.xOffset = 15 + bar.keyframeDuration = 1.2 + + return bar + }() + + var currentProgress: CGFloat = 0 override func viewDidLoad() { super.viewDidLoad() - self.configureLinearProgressBar() + self.view.addSubview(linearBar) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } + + @IBAction func advanceProgress(_ sender: AnyObject) { + currentProgress += 0.25 + if currentProgress > 1 { + currentProgress = 0 + } + + self.linearBar.showProgress(currentProgress, duration: 0.3) + } @IBAction func startAnimation(_ sender: AnyObject) { - self.linearBar.startAnimation() + self.linearBar.show(duration: 0.3, delay: 0.0) } @IBAction func stopAnimation(_ sender: AnyObject) { - self.linearBar.stopAnimation() - } - - //----- - - fileprivate func configureLinearProgressBar(){ - linearBar.backgroundColor = UIColor(red:0.68, green:0.81, blue:0.72, alpha:1.0) - linearBar.progressBarColor = UIColor(red:0.26, green:0.65, blue:0.45, alpha:1.0) - linearBar.heightForLinearBar = 5 + self.linearBar.dismiss(duration: 0.3) } } diff --git a/LinearProgressBarMaterial.podspec b/LinearProgressBarMaterial.podspec index eb2bf7c..a93c8c4 100755 --- a/LinearProgressBarMaterial.podspec +++ b/LinearProgressBarMaterial.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "LinearProgressBarMaterial" -s.version = "1.2" +s.version = "2.0" s.summary = "LinearProgressBarMaterial" s.description = "A simple Linear Progress Bar for IOS (Swift 3.0), inspired by Material Design" s.homepage = "https://github.com/PhilippeBoisney/LinearProgressBar" diff --git a/Pod/Classes/LinearProgressBar.swift b/Pod/Classes/LinearProgressBar.swift index 4d0ffa4..55a96db 100644 --- a/Pod/Classes/LinearProgressBar.swift +++ b/Pod/Classes/LinearProgressBar.swift @@ -10,144 +10,250 @@ import UIKit +fileprivate var screenSize: CGRect { + return UIScreen.main.bounds +} + open class LinearProgressBar: UIView { - - //FOR DATA - fileprivate var screenSize: CGRect = UIScreen.main.bounds - fileprivate var isAnimationRunning = false - - //FOR DESIGN - fileprivate var progressBarIndicator: UIView! - - //PUBLIC VARS - open var backgroundProgressBarColor: UIColor = UIColor(red:0.73, green:0.87, blue:0.98, alpha:1.0) - open var progressBarColor: UIColor = UIColor(red:0.12, green:0.53, blue:0.90, alpha:1.0) - open var heightForLinearBar: CGFloat = 5 - open var widthForLinearBar: CGFloat = 0 - - public init () { - super.init(frame: CGRect(origin: CGPoint(x: 0,y :20), size: CGSize(width: screenSize.width, height: 0))) - self.progressBarIndicator = UIView(frame: CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: 0, height: heightForLinearBar))) - } - - override public init(frame: CGRect) { - super.init(frame: frame) - self.progressBarIndicator = UIView(frame: CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: 0, height: heightForLinearBar))) - } - - required public init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - //MARK: LIFE OF VIEW - override open func layoutSubviews() { - super.layoutSubviews() - self.screenSize = UIScreen.main.bounds - - if widthForLinearBar == 0 || widthForLinearBar == self.screenSize.height { - widthForLinearBar = self.screenSize.width - } - - if (UIDeviceOrientationIsLandscape(UIDevice.current.orientation)) { - self.frame = CGRect(origin: CGPoint(x: self.frame.origin.x,y :self.frame.origin.y), size: CGSize(width: widthForLinearBar, height: self.frame.height)) - } - - if (UIDeviceOrientationIsPortrait(UIDevice.current.orientation)) { - self.frame = CGRect(origin: CGPoint(x: self.frame.origin.x,y :self.frame.origin.y), size: CGSize(width: widthForLinearBar, height: self.frame.height)) - } - } - - //MARK: PUBLIC FUNCTIONS ------------------------------------------------------------------------------------------ - - //Start the animation - open func startAnimation(){ - - self.configureColors() - - self.show() - - if !isAnimationRunning { - self.isAnimationRunning = true - - UIView.animate(withDuration: 0.5, delay:0, options: [], animations: { - self.frame = CGRect(x: 0, y: self.frame.origin.y, width: self.widthForLinearBar, height: self.heightForLinearBar) - }, completion: { animationFinished in - self.addSubview(self.progressBarIndicator) - self.configureAnimation() - }) - } - } - - //Start the animation - open func stopAnimation() { - - self.isAnimationRunning = false - - UIView.animate(withDuration: 0.5, animations: { - self.progressBarIndicator.frame = CGRect(x: 0, y: 0, width: self.widthForLinearBar, height: 0) - self.frame = CGRect(x: 0, y: self.frame.origin.y, width: self.widthForLinearBar, height: 0) - }) - } - - //MARK: PRIVATE FUNCTIONS ------------------------------------------------------------------------------------------ - - fileprivate func show() { - - // Only show once - if self.superview != nil { - return - } - - // Find current top viewcontroller - if let topController = getTopViewController() { - let superView: UIView = topController.view - superView.addSubview(self) - } - } - - fileprivate func configureColors(){ - - self.backgroundColor = self.backgroundProgressBarColor - self.progressBarIndicator.backgroundColor = self.progressBarColor - self.layoutIfNeeded() - } - - fileprivate func configureAnimation() { - - guard let superview = self.superview else { - stopAnimation() - return - } - - self.progressBarIndicator.frame = CGRect(origin: CGPoint(x: 0, y :0), size: CGSize(width: 0, height: heightForLinearBar)) - - UIView.animateKeyframes(withDuration: 1.0, delay: 0, options: [], animations: { - - UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.5, animations: { - self.progressBarIndicator.frame = CGRect(x: 0, y: 0, width: self.widthForLinearBar*0.7, height: self.heightForLinearBar) - }) - - UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.5, animations: { - self.progressBarIndicator.frame = CGRect(x: superview.frame.width, y: 0, width: 0, height: self.heightForLinearBar) - - }) - - }) { (completed) in - if (self.isAnimationRunning){ - self.configureAnimation() - } - } - } - - // ----------------------------------------------------- - //MARK: UTILS --------------------------------------- - // ----------------------------------------------------- - - fileprivate func getTopViewController() -> UIViewController? { - var topController: UIViewController? = UIApplication.shared.keyWindow?.rootViewController - while topController?.presentedViewController != nil { - topController = topController?.presentedViewController - } - return topController - } + + // MARK: - Private Variables + + fileprivate var isAnimationRunning = false + + fileprivate lazy var progressBarIndicator: UIView = { + let frame = CGRect(origin: CGPoint(x: 0, y:0), size: CGSize(width: 0, height: self.progressBarHeight)) + return UIView(frame: frame) + }() + + + // MARK: Public Variables + + open var progressBarHeight: CGFloat + + /// Background color for the progress bar + open var progressBarColor: UIColor = UIColor(red:0.12, green:0.53, blue:0.90, alpha:1.0) + + /// Used to determine how much variation the progress bar should animate + open var widthRatioOffset: CGFloat = 0.7 + + /// The offset used to determine how far offscreen the progress bar should start and finish animation + open var xOffset: CGFloat = 0 + + /// The progress bar animation duration + open var keyframeDuration: TimeInterval = 1.0 + + + // MARK: Deprecated + + @available(*, deprecated, message: "Please use backgroundColor instead", renamed: "backgroundColor") + var backgroundProgressBarColor: UIColor = UIColor.white + + @available(*, deprecated, message: "Please use progressBarHeight instead", renamed: "progressBarHeight") + var heightForLinearBar: CGFloat = 5 + + @available(*, deprecated, message: "Please adjust frame.size.width instead") + var widthForLinearBar: CGFloat = 0 + + + // MARK: Inits + + public convenience init(height: CGFloat = 5) { + self.init(frame: CGRect(origin: CGPoint(x: 0,y :20), size: CGSize(width: screenSize.width, height: height))) + } + + override public init(frame: CGRect) { + progressBarHeight = frame.height + var frame = frame + frame.size.height = 0 + super.init(frame: frame) + self.clipsToBounds = true + } + + required public init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + //MARK: - Public Functions + + override open func layoutSubviews() { + super.layoutSubviews() + + var rect = self.frame + + if rect.width == 0 || rect.width == screenSize.height { + rect.size.width = screenSize.width + } + + self.frame = rect + } + + /** + Shows the view, if not currently shown, then starts the animation + + - parameters: + - duration: The animation duration for showing the view. Defaults to `0.5` + - delay: The delay for showing the view. Defaults to `0.0` + */ + open func show(duration: TimeInterval = 0.5, delay: TimeInterval = 0) { + + self.display() + + guard !isAnimationRunning else {return} + self.isAnimationRunning = true + + var rect = self.frame + rect.size.height = self.progressBarHeight + + UIView.animate(withDuration: duration, delay: delay, options: [], animations: { + self.frame = rect + }) { animationFinished in + self.addSubview(self.progressBarIndicator) + self.configureAnimations() + } + } + + /** + Shows the view, if not currently shown, then displays a specific progress value. This is useful for displaying progress of a task. + + - parameters: + - progress: The progress of the task. Should be a value between `0.0` & `1.0` + - duration: The animation duration for showing the view. Defaults to `0.5` + */ + open func showProgress(_ progress: CGFloat, duration: TimeInterval = 0.5) { + + self.display() + + self.isAnimationRunning = false + + var rect = self.frame + rect.size.height = self.progressBarHeight + + var progressRect = self.progressBarIndicator.frame + progressRect.origin = CGPoint.zero + self.progressBarIndicator.frame = progressRect + + progressRect.size.width = self.frame.width * progress + + UIView.animate(withDuration: duration, delay: 0, options: [], animations: { + self.frame = rect + }) { animationFinished in + self.addSubview(self.progressBarIndicator) + UIView.animate(withDuration: duration) { + self.progressBarIndicator.frame = progressRect + } + } + } + + /** + Dismisses the view, if currently shown. + + - parameters: + - duration: The animation duration for dismissing the view. Defaults to `0.5` + */ + open func dismiss(duration: TimeInterval = 0.5) { + + self.isAnimationRunning = false + + var rect = self.frame + rect.size.height = 0 + + UIView.animate(withDuration: duration, animations: { + self.frame = rect + }) { (finished: Bool) in + self.progressBarIndicator.removeFromSuperview() + } + } + + + //MARK: Private Functions + + fileprivate func display() { + self.progressBarIndicator.backgroundColor = self.progressBarColor + self.layoutIfNeeded() + + guard self.superview == nil, let view = UIApplication.shared.keyWindow?.visibleViewController?.view else {return} + view.addSubview(self) + } + + fileprivate func configureAnimations() { + + guard let _ = self.superview else { + dismiss() + return + } + + guard self.isAnimationRunning else {return} + + self.progressBarIndicator.frame = CGRect(origin: CGPoint(x: 0, y :0), size: CGSize(width: 0, height: progressBarHeight)) + + UIView.animateKeyframes(withDuration: keyframeDuration, delay: 0, options: [], animations: { + + UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: self.keyframeDuration/2) { + self.progressBarIndicator.frame = CGRect(x: -self.xOffset, y: 0, width: self.frame.width * self.widthRatioOffset, height: self.progressBarHeight) + } + + UIView.addKeyframe(withRelativeStartTime: self.keyframeDuration/2, relativeDuration: self.keyframeDuration/2) { + self.progressBarIndicator.frame = CGRect(x: self.frame.width, y: 0, width: self.xOffset, height: self.progressBarHeight) + } + + }) { (completed) in + guard self.isAnimationRunning else {return} + self.configureAnimations() + } + } + + + // MARK: Deprecated + + @available(*, deprecated, message: "Please use show() instead", renamed: "show") + func startAnimation() { + self.show() + } + + @available(*, deprecated, message: "Please use dismiss() instead", renamed: "dismiss") + func stopAnimation() { + self.dismiss() + } +} + + +// MARK: - + +fileprivate extension UIWindow { + + /** + Returns the currently visible view controller + + - returns: The visible view controller + */ + var visibleViewController: UIViewController? { + return getVisibleViewController(forRootController: rootViewController) + } + + /** + Returns the visible view controller + + - parameters: + - currentRootViewController: Current Root View Controller + - returns: The visible view controller + */ + func getVisibleViewController(forRootController currentRootViewController: UIViewController?) -> UIViewController? { + + guard let controller = currentRootViewController else {return nil} + + switch controller { + + case let navVC as UINavigationController: + return getVisibleViewController(forRootController: navVC.viewControllers.last) + + case let tabVC as UITabBarController: + return getVisibleViewController(forRootController: tabVC.selectedViewController) + + case let controller where controller.presentedViewController != nil: + return getVisibleViewController(forRootController: controller.presentedViewController) + + default: + return controller + } + } } diff --git a/README.md b/README.md index 7fbca64..b08aa4b 100755 --- a/README.md +++ b/README.md @@ -1,11 +1,8 @@ # Linear Progress Bar (Material Design) -[![Platform](http://img.shields.io/badge/platform-ios-blue.svg?style=flat -)](https://developer.apple.com/iphone/index.action) -[![Language](http://img.shields.io/badge/language-swift-brightgreen.svg?style=flat -)](https://developer.apple.com/swift) -[![License](http://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat -)](http://mit-license.org) +[![Platform](http://img.shields.io/badge/platform-ios-blue.svg?style=flat)](https://developer.apple.com/iphone/index.action) +[![Language](http://img.shields.io/badge/language-swift-brightgreen.svg?style=flat)](https://developer.apple.com/swift) +[![License](http://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat)](http://mit-license.org) Linear Progress Bar (inspired by [Google Material Design](https://www.google.com/design/spec/components/progress-activity.html#progress-activity-types-of-indicators#)) for iOS written in Swift 3.0 @@ -30,22 +27,22 @@ end ## USAGE ```swift //Simply, Call Progress Bar -let linearBar: LinearProgressBar = LinearProgressBar() +let linearBar = LinearProgressBar() -//Start Animation -self.linearBar.startAnimation() +//Show and Start Animation +self.linearBar.show() -//Stop Animation -self.linearBar.stopAnimation() +//Show Specific Progress +self.linearBar.showProgress(progress: 0.5) + +//Dismiss +self.linearBar.dismiss() ``` **OPTIONS** ```swift //Change background color linearBar.backgroundColor = UIColor(red:0.68, green:0.81, blue:0.72, alpha:1.0) linearBar.progressBarColor = UIColor(red:0.26, green:0.65, blue:0.45, alpha:1.0) - -//Change height of progressBar -linearBar.heightForLinearBar = 5 ``` ## FEATURES @@ -56,7 +53,7 @@ linearBar.heightForLinearBar = 5 - [x] Swift 3 support ## Version -1.2 +2.0 ## Author