Skip to content

Instantly share code, notes, and snippets.

@damodarnamala
Created January 5, 2019 20:23
Show Gist options
  • Save damodarnamala/7f0f484708f60c996772ae28e5e1c615 to your computer and use it in GitHub Desktop.
Save damodarnamala/7f0f484708f60c996772ae28e5e1c615 to your computer and use it in GitHub Desktop.
IOS Swift Progress menu example
protocol StepMenuDelegate {
func didSelectItem(atIndex index: NSInteger)
}
let NUM_OF_ITEMS = 4
@IBDesignable
class StepView: UIView {
var delegate : StepMenuDelegate!
var titles: [String] = [] {
didSet(values) {
}
}
@IBInspectable
var itemSize: CGFloat = 34{
didSet(values) {
}
}
@IBInspectable
var lineWidth: CGFloat = 4 {
didSet(values) {
self.layoutSublayers(of: self.layer)
}
}
var offSet: CGFloat = 8
private var itemOffset : CGFloat = 8 {
didSet (value) {
}
}
@IBInspectable
var circleColor : UIColor = UIColor.orange {
didSet (value) {
self.layoutSublayers(of: self.layer)
}
}
@IBInspectable
var completedCircleColor : UIColor = UIColor.purple {
didSet (value) {
self.layoutSublayers(of: self.layer)
}
}
@IBInspectable
var completedStepLineColor : UIColor = UIColor.red {
didSet (value) {
self.layoutSublayers(of: self.layer)
}
}
@IBInspectable var selectedIndex : Int = 1000{
didSet (value) {
self.layoutSublayers(of: self.layer)
}
}
@IBInspectable
var lineColor : UIColor = UIColor.lightGray.withAlphaComponent(0.25) {
didSet (value) {
self.layoutSublayers(of: self.layer)
}
}
private var path : UIBezierPath!
var selectedLayer : CAShapeLayer!
var buttons: [UIButton]!
private var parentPathRect : CGRect!
override func awakeFromNib() {
super.awakeFromNib()
}
override func layoutSubviews() {
self.setup()
}
func setup() {
self.setNeedsDisplay()
if let layers = self.layer.sublayers as? [CAShapeLayer] {
for layet in layers {
layet.removeFromSuperlayer()
}
}
let layer = CAShapeLayer()
self.parentPathRect = CGRect(origin: CGPoint(x: offSet,
y: self.bounds.midY - (self.lineWidth/2) ),
size: CGSize(width: self.bounds.width - (offSet * 2),
height: lineWidth))
path = UIBezierPath(roundedRect: self.parentPathRect, cornerRadius: 2)
layer.path = path.cgPath
layer.fillColor = self.lineColor.cgColor
layer.lineCap = .round
self.layer.addSublayer(layer)
var xPos: CGFloat = 0
itemOffset = itemSize
let itemWidth = ((self.layer.bounds.size.width - (itemSize))/CGFloat(NUM_OF_ITEMS))
for i in 0..<NUM_OF_ITEMS {
xPos = itemWidth * CGFloat(i)
let rect = CGRect(x:xPos + itemWidth/2 , y:self.layer.bounds.midY - (itemSize * 0.5) , width: itemSize, height: itemSize)
let cirlceLayer = ShapeLayer.layer(frame: rect)
cirlceLayer.name = "\(i)"
cirlceLayer.fillColor = circleColor.cgColor
self.layer.addSublayer(cirlceLayer)
}
guard let sublayers = self.layer.sublayers as? [CAShapeLayer] else { return }
for layer in sublayers {
if layer.name != nil {
if self.selectedIndex == Int(layer.name!) {
let toPoint: CGFloat!
if self.selectedIndex == NUM_OF_ITEMS - 1 {
toPoint = (path.bounds.size.width);
self.drawSelectedPath(from: offSet, to: toPoint)
} else {
toPoint = (layer.path?.boundingBox.origin.x)!;
self.drawSelectedPath(from: offSet, to: toPoint)
}
}
if Int(layer.name!)! <= self.selectedIndex{
layer.fillColor = completedCircleColor.cgColor
}
}
}
}
func setUpLabels() {
}
func drawSelectedPath( from : CGFloat, to : CGFloat) {
let rect = CGRect(x: from, y: self.layer.bounds.midY - lineWidth/2, width: to, height: lineWidth)
let path = UIBezierPath(roundedRect: rect, cornerRadius: 2)
let layer = CAShapeLayer()
layer.path = path.cgPath
layer.zPosition = -1
layer.fillColor = self.completedStepLineColor.cgColor
layer.lineCap = .round
self.layer.addSublayer(layer)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
guard let point = touch?.location(in: self) else { return }
guard let sublayers = self.layer.sublayers as? [CAShapeLayer] else { return }
for layer in sublayers {
if let path = layer.path, path.contains(point) {
if let name = layer.name {
print("Name: ",name)
}
}
}
}
}
class ShapeLayer : CAShapeLayer {
static func layer(frame:CGRect) -> CAShapeLayer {
let circleLayer = CAShapeLayer()
let radius: CGFloat = frame.size.height/2
circleLayer.path = UIBezierPath(roundedRect: CGRect(x: frame.origin.x, y: frame.origin.y, width: frame.size.height , height: frame.size.height ), cornerRadius: radius).cgPath
return circleLayer
}
}
import UIKit
import CoreGraphics
class ViewController: UIViewController, StepMenuDelegate {
@IBOutlet weak var stepView: StepView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.stepView.delegate = self;
self.stepView.titles = ["One", "Two", "Three"]
self.stepView.lineWidth = 4
self.stepView.circleColor = UIColor.lightGray
self.stepView.lineColor = UIColor.darkGray.withAlphaComponent(0.25)
self.stepView.selectedIndex = 2
}
func didSelectItem(atIndex index: NSInteger) {
print(index)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment