//
// ConnectorView.swift
//
// Created by harsh vishwakrama on 5/24/18.
//
import UIKit
private let grayColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
private let purpleColor = UIColor(red: 0.387, green: 0.416, blue: 0.718, alpha: 1.000)
@IBDesignable
class ConnectorView: UIView {
var mode: Mode = .end{
didSet{
let width = bounds.width
let height = bounds.height
let halfWidth = bounds.width / 2
let halfHeight = bounds.height / 2
let thirdWidth = bounds.width / 3
let strokeWidth = width / 5
let midPoint = CGPoint(x: bounds.midX, y: bounds.midY)
switch mode {
case .start:
drawStart(width, thirdWidth, halfWidth, halfHeight, midPoint,strokeWidth)
case .node:
drawNode(halfWidth, thirdWidth, halfHeight, midPoint,strokeWidth)
case .end:
drawEnd(halfWidth, thirdWidth, halfHeight, midPoint,strokeWidth)
case .only:
drawOnly(width, thirdWidth, halfWidth, halfHeight, strokeWidth, midPoint)
}
layoutSubviews()
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
clipsToBounds = true
}
enum Mode {
case start, node, end, only
}
}
extension ConnectorView{
fileprivate func drawStart(_ width: CGFloat, _ thirdWidth: CGFloat, _ halfWidth: CGFloat, _ halfHeight: CGFloat, _ midPoint: CGPoint, _ strokeWidth: CGFloat) {
layer.sublayers?.forEach{ layer in
layer.removeFromSuperlayer()
}
let linePathTop = UIBezierPath()
linePathTop.move(to: CGPoint(x: -width, y: -thirdWidth))
linePathTop.addCurve(to: CGPoint(x: halfWidth, y: halfHeight - thirdWidth), controlPoint1: CGPoint(x: halfWidth, y: -thirdWidth ), controlPoint2: CGPoint(x: halfWidth, y: -thirdWidth))
linePathTop.move(to: CGPoint(x: 2 * width, y: -thirdWidth))
linePathTop.addCurve(to: CGPoint(x: halfWidth, y: halfHeight - thirdWidth), controlPoint1: CGPoint(x: halfWidth, y: -thirdWidth ), controlPoint2: CGPoint(x: halfWidth, y: -thirdWidth))
linePathTop.move(to: CGPoint(x: 0, y: -thirdWidth))
linePathTop.addLine(to: CGPoint(x: width, y: -thirdWidth))
linePathTop.move(to: CGPoint(x: halfWidth, y: -thirdWidth))
linePathTop.addLine(to: CGPoint(x: halfWidth, y: halfHeight - thirdWidth))
linePathTop.close()
let shapeLayerTop = CAShapeLayer()
shapeLayerTop.path = linePathTop.cgPath
shapeLayerTop.fillColor = UIColor.clear.cgColor
shapeLayerTop.strokeColor = purpleColor.cgColor
shapeLayerTop.lineWidth = strokeWidth
layer.addSublayer(shapeLayerTop)
let shapeLayerBottom = CAShapeLayer()
let linePathBottom = UIBezierPath()
linePathBottom.move(to: CGPoint(x: halfWidth, y: halfHeight + thirdWidth))
linePathBottom.addLine(to: CGPoint(x: halfWidth, y: bounds.height))
linePathBottom.close()
shapeLayerBottom.path = linePathBottom.cgPath
shapeLayerBottom.strokeColor = grayColor.cgColor
shapeLayerBottom.fillColor = UIColor.clear.cgColor
shapeLayerBottom.lineWidth = strokeWidth
layer.addSublayer(shapeLayerBottom)
let shapeLayerMid = CAShapeLayer()
let circlePath = UIBezierPath(arcCenter: midPoint , radius: thirdWidth, startAngle: 0, endAngle: CGFloat(Double.pi * 2), clockwise: true)
shapeLayerMid.path = circlePath.cgPath
shapeLayerMid.strokeColor = grayColor.cgColor
shapeLayerMid.fillColor = UIColor.clear.cgColor
shapeLayerMid.lineWidth = strokeWidth
layer.addSublayer(shapeLayerMid)
}
fileprivate func drawEnd(_ halfWidth: CGFloat, _ thirdWidth: CGFloat, _ halfHeight: CGFloat, _ midPoint: CGPoint,_ strokeWidth: CGFloat) {
layer.sublayers?.forEach{ layer in
layer.removeFromSuperlayer()
}
let linePath = UIBezierPath()
linePath.move(to: CGPoint(x: halfWidth, y: -thirdWidth))
linePath.addLine(to: CGPoint(x: halfWidth, y: halfHeight - thirdWidth))
linePath.close()
let shapeLayerLine = CAShapeLayer()
shapeLayerLine.fillColor = UIColor.clear.cgColor
shapeLayerLine.strokeColor = grayColor.cgColor
shapeLayerLine.lineWidth = strokeWidth
shapeLayerLine.path = linePath.cgPath
layer.addSublayer(shapeLayerLine)
let shapeLayerMid = CAShapeLayer()
let circlePath = UIBezierPath(arcCenter: midPoint , radius: thirdWidth, startAngle: 0, endAngle: CGFloat(Double.pi * 2), clockwise: true)
shapeLayerMid.path = circlePath.cgPath
shapeLayerMid.strokeColor = grayColor.cgColor
shapeLayerMid.fillColor = UIColor.clear.cgColor
shapeLayerMid.lineWidth = strokeWidth
layer.addSublayer(shapeLayerMid)
}
fileprivate func drawNode(_ halfWidth: CGFloat, _ thirdWidth: CGFloat, _ halfHeight: CGFloat, _ midPoint: CGPoint,_ strokeWidth: CGFloat) {
layer.sublayers?.forEach{ layer in
layer.removeFromSuperlayer()
}
let linePath = UIBezierPath()
linePath.move(to: CGPoint(x: halfWidth, y: -thirdWidth))
linePath.addLine(to: CGPoint(x: halfWidth, y: halfHeight - thirdWidth))
linePath.move(to: CGPoint(x: halfWidth, y: halfHeight + thirdWidth))
linePath.addLine(to: CGPoint(x: halfWidth, y: bounds.height))
linePath.close()
let shapeLayerLine = CAShapeLayer()
shapeLayerLine.fillColor = UIColor.clear.cgColor
shapeLayerLine.strokeColor = grayColor.cgColor
shapeLayerLine.lineWidth = strokeWidth
shapeLayerLine.path = linePath.cgPath
layer.addSublayer(shapeLayerLine)
let shapeLayerMid = CAShapeLayer()
let circlePath = UIBezierPath(arcCenter: midPoint , radius: thirdWidth, startAngle: 0, endAngle: CGFloat(Double.pi * 2), clockwise: true)
shapeLayerMid.path = circlePath.cgPath
shapeLayerMid.strokeColor = grayColor.cgColor
shapeLayerMid.fillColor = UIColor.clear.cgColor
shapeLayerMid.lineWidth = strokeWidth
layer.addSublayer(shapeLayerMid)
}
fileprivate func drawOnly(_ width: CGFloat, _ thirdWidth: CGFloat, _ halfWidth: CGFloat, _ halfHeight: CGFloat, _ strokeWidth: CGFloat, _ midPoint: CGPoint) {
layer.sublayers?.forEach{ layer in
layer.removeFromSuperlayer()
}
let linePathTop = UIBezierPath()
linePathTop.move(to: CGPoint(x: -width, y: -thirdWidth))
linePathTop.addCurve(to: CGPoint(x: halfWidth, y: halfHeight - thirdWidth), controlPoint1: CGPoint(x: halfWidth, y: -thirdWidth ), controlPoint2: CGPoint(x: halfWidth, y: -thirdWidth))
linePathTop.move(to: CGPoint(x: 2 * width, y: -thirdWidth))
linePathTop.addCurve(to: CGPoint(x: halfWidth, y: halfHeight - thirdWidth), controlPoint1: CGPoint(x: halfWidth, y: -thirdWidth ), controlPoint2: CGPoint(x: halfWidth, y: -thirdWidth))
linePathTop.move(to: CGPoint(x: 0, y: -thirdWidth))
linePathTop.addLine(to: CGPoint(x: width, y: -thirdWidth))
linePathTop.move(to: CGPoint(x: halfWidth, y: -thirdWidth))
linePathTop.addLine(to: CGPoint(x: halfWidth, y: halfHeight - thirdWidth))
linePathTop.close()
let shapeLayerTop = CAShapeLayer()
shapeLayerTop.path = linePathTop.cgPath
shapeLayerTop.fillColor = UIColor.clear.cgColor
shapeLayerTop.strokeColor = purpleColor.cgColor
shapeLayerTop.lineWidth = strokeWidth
layer.addSublayer(shapeLayerTop)
let shapeLayerMid = CAShapeLayer()
let circlePath = UIBezierPath(arcCenter: midPoint , radius: thirdWidth, startAngle: 0, endAngle: CGFloat(Double.pi * 2), clockwise: true)
shapeLayerMid.path = circlePath.cgPath
shapeLayerMid.strokeColor = grayColor.cgColor
shapeLayerMid.fillColor = UIColor.clear.cgColor
shapeLayerMid.lineWidth = strokeWidth
layer.addSublayer(shapeLayerMid)
}
}
Это первое решение, которое мне удалось найти.Может потребоваться некоторые настройки, но это работает для меня.Мне нужно 3 этапа пользовательского интерфейса для размещения в UITableViewCell.Один для первой ячейки, один для последней ячейки и другой для оставшихся ячеек.
Результат примерно такой: