Created
July 10, 2018 14:33
-
-
Save nthState/58cc50bf5c29d2f1765d32a915a49fc1 to your computer and use it in GitHub Desktop.
Vertical Progress Bar with stepper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import UIKit | |
@IBDesignable class VerticalProgressionBar : UIView { | |
@IBInspectable var sections: Int = 1 { | |
didSet { | |
build() | |
} | |
} | |
@IBInspectable var filled: Int = 0 { | |
didSet { | |
build() | |
} | |
} | |
@IBInspectable var nonFillColor: UIColor = .orange | |
@IBInspectable var fillColor: UIColor = .green | |
@IBInspectable var strokeColor: UIColor = .blue | |
@IBInspectable var strokeWidth: Float = 2.0 | |
@IBInspectable var seperatorHeight: Float = 1.0 | |
required init?(coder aDecoder: NSCoder) { | |
super.init(coder: aDecoder) | |
} | |
override init(frame: CGRect) { | |
super.init(frame: frame) | |
} | |
override func layoutSubviews() { | |
super.layoutSubviews() | |
build() | |
} | |
func build() { | |
self.backgroundColor = nonFillColor | |
self.layer.sublayers?.removeAll() | |
setupRoundedCorners() | |
setupBorder() | |
setupFillSections() | |
setupSectionDividers() | |
} | |
func setupRoundedCorners() { | |
self.layer.cornerRadius = getCornerRadius() | |
} | |
func getCornerRadius() -> CGFloat { | |
let width = self.frame.size.width | |
return width / 2 | |
} | |
func setupBorder() { | |
self.layer.borderColor = strokeColor.cgColor | |
self.layer.borderWidth = CGFloat(strokeWidth) | |
} | |
func getClippingMask() -> CAShapeLayer { | |
let mask = UIBezierPath(roundedRect: self.bounds, cornerRadius: getCornerRadius()) | |
let clippingMask = CAShapeLayer() | |
clippingMask.fillRule = kCAFillRuleEvenOdd | |
clippingMask.path = mask.cgPath | |
return clippingMask | |
} | |
func setupSectionDividers() { | |
if sections == 0 { | |
return | |
} | |
let width = self.frame.size.width | |
let sectionHeight = self.frame.size.height / CGFloat(sections) | |
for section in 1..<sections { | |
let y: CGFloat = CGFloat(section) * sectionHeight | |
let path = UIBezierPath() | |
path.move(to: CGPoint(x: 0, y: y)) | |
path.addLine(to: CGPoint(x: width, y: y)) | |
let row = CAShapeLayer() | |
row.name = "row" | |
row.path = path.cgPath | |
row.fillColor = UIColor.clear.cgColor | |
row.strokeColor = strokeColor.cgColor | |
row.lineWidth = CGFloat(seperatorHeight) | |
row.lineCap = kCALineCapRound | |
row.mask = getClippingMask() | |
self.layer.addSublayer(row) | |
} | |
} | |
func setupFillSections() { | |
if filled == 0 { | |
return | |
} | |
let width = self.frame.size.width | |
let height = self.frame.size.height | |
let sectionHeight = height / CGFloat(sections) | |
for fill in 0...filled { | |
let y: CGFloat = height - (CGFloat(fill) * sectionHeight) | |
let rect = CGRect(x: 0, y: y, width: width, height: sectionHeight) | |
let path = UIBezierPath(rect: rect) | |
let row = CAShapeLayer() | |
row.name = "row" | |
row.path = path.cgPath | |
row.fillColor = fillColor.cgColor | |
row.mask = getClippingMask() | |
self.layer.addSublayer(row) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment