iOS 使用 CAShapeLayer 绘制自定义形状
iOS Draw Custom Shape using CAShapeLayer
我想画一个类似于下图的自定义形状。
- 一条倒圆角的线
- 空心圆
- 后面还有一行
I achieved this in Android in the following way.
float radiusClear = halfWidth - strokeSize / 2f; // 1
canvas.drawRect(0, 0, width, radiusClear, rootPaint); // 2
canvas.drawCircle(0, radiusClear, radiusClear, clearPaint); // 3
canvas.drawCircle(width, radiusClear, radiusClear, clearPaint); // 4
canvas.drawLine(halfWidth, 0, halfWidth, halfHeight, rootPaint); // 5
canvas.drawLine(halfWidth, halfHeight, halfWidth, height, iconPaint); // 6
canvas.drawCircle(halfWidth, halfHeight, halfWidth, iconPaint); // 7
canvas.drawCircle(halfWidth, halfHeight, thirdWidth, clearPaint); // 8
- 其中 (1) 计算距离。
- (2) 在顶部画一个矩形
- (3) (4) 画两个圆清除矩形,使它看起来像两个圆弧
- 然后其余的调用以类似的方式绘制剩余的视图。
在 swift 上有什么等效或更好的方法?
如果它不是自定义视图,您可以使用 CAShape 层和 UIBezierPath 来执行此操作 // 如果它的自定义视图更容易,只需在绘图中创建路径并设置颜色,下面是您需要创建路径的一些方法和其他方法设置颜色等属性。如果不是自定义视图,您可以使用带有路径的 CAShapelayer 来实现相同的目的。
//create your path
let xpos: CGFloat = yourXpos // do your calculation and set the x and y
let ypos:cfFloat = yourYPos
let path = UIBezierPath() // UIBezierPath is like a pan you draw line arch circle, like pen you can move from one position to another, if you want to close(connected starting and end point) you just call close()
path.move(to: CGPoint(x: xpos, y: yPos)) //move is like the
path.addLine(to: CGPoint(x: xpos , y: yPos + 25))
path.addArc(withCenter: CGPoint(x: xpos + 1, y: yPos + 25), radius: 2, startAngle: 0, endAngle: CGFloat(Double.pi * 2), clockwise: true)
path.close()
path.move()//move to some new place
You have to calculate x,y like you already done for Android and just set the correct x and y values
//create shape layer and set the path you just created to the shapelayer and shapelayer to your view
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
self.yourView.layer.addSublayer(shapeLayer)
shapeLayer.lineWidth = 0.5 // setting the stoke width// thinkness of drawing
you can set the stroke colour or can fill it
shapeLayer.fillColor = UIColor.black.cgColor
shapeLayer.strokeColor = UIColor.green.cgColor
PS: I Haven't done the actual calculation but you have already done, so maybe with above help you can easly replicate for iOS.
我按照你的要求做了快速代码。希望对你有帮助。
//// Color Declarations
let color = UIColor(red: 0.387, green: 0.416, blue: 0.718, alpha: 1.000)
let color2 = UIColor(red: 1.000, green: 1.000, blue: 1.000, alpha: 1.000)
let color3 = UIColor(red: 1.000, green: 1.000, blue: 1.000, alpha: 1.000)
let color4 = UIColor(red: 0.300, green: 0.586, blue: 0.712, alpha: 1.000)
//// Oval Drawing
let ovalPath = UIBezierPath(ovalIn: CGRect(x: 41, y: 39, width: 20, height: 20))
color.setStroke()
ovalPath.lineWidth = 2.5
ovalPath.stroke()
//// Rectangle 2 Drawing
let rectangle2Path = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 100, height: 17))
color4.setFill()
rectangle2Path.fill()
//// Bezier 2 Drawing
let bezier2Path = UIBezierPath()
bezier2Path.move(to: CGPoint(x: -6.5, y: 18.5))
bezier2Path.addCurve(to: CGPoint(x: 41.76, y: 18.5), controlPoint1: CGPoint(x: 40.61, y: 18.5), controlPoint2: CGPoint(x: 41.76, y: 18.5))
bezier2Path.addCurve(to: CGPoint(x: 47.5, y: 22.7), controlPoint1: CGPoint(x: 41.76, y: 18.5), controlPoint2: CGPoint(x: 47.5, y: 18.5))
bezier2Path.addCurve(to: CGPoint(x: 47.5, y: 39.5), controlPoint1: CGPoint(x: 47.5, y: 26.9), controlPoint2: CGPoint(x: 47.5, y: 39.5))
color3.setStroke()
bezier2Path.lineWidth = 1
bezier2Path.stroke()
//// Bezier 3 Drawing
let bezier3Path = UIBezierPath()
bezier3Path.move(to: CGPoint(x: 100.5, y: 17.5))
bezier3Path.addCurve(to: CGPoint(x: 58.5, y: 17.5), controlPoint1: CGPoint(x: 59.5, y: 17.5), controlPoint2: CGPoint(x: 58.5, y: 17.5))
bezier3Path.addCurve(to: CGPoint(x: 55.5, y: 21.5), controlPoint1: CGPoint(x: 58.5, y: 17.5), controlPoint2: CGPoint(x: 55.5, y: 18.5))
bezier3Path.addCurve(to: CGPoint(x: 55.5, y: 39.5), controlPoint1: CGPoint(x: 55.5, y: 24.5), controlPoint2: CGPoint(x: 55.5, y: 39.5))
color2.setStroke()
bezier3Path.lineWidth = 1
bezier3Path.stroke()
//// Rectangle Drawing
let rectanglePath = UIBezierPath(rect: CGRect(x: 47, y: 59, width: 8, height: 41))
color.setFill()
rectanglePath.fill()
//
// 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)
}
}
这是我想到的第一个解决方案。可能需要一些调整,但这对我有用。我需要 UI 的 3 个阶段来放置在 UITableViewCell 中。
一个用于第一个单元格,一个用于最后一个单元格,另一个用于其余单元格。
结果是这样的
我想画一个类似于下图的自定义形状。
- 一条倒圆角的线
- 空心圆
- 后面还有一行
I achieved this in Android in the following way.
float radiusClear = halfWidth - strokeSize / 2f; // 1
canvas.drawRect(0, 0, width, radiusClear, rootPaint); // 2
canvas.drawCircle(0, radiusClear, radiusClear, clearPaint); // 3
canvas.drawCircle(width, radiusClear, radiusClear, clearPaint); // 4
canvas.drawLine(halfWidth, 0, halfWidth, halfHeight, rootPaint); // 5
canvas.drawLine(halfWidth, halfHeight, halfWidth, height, iconPaint); // 6
canvas.drawCircle(halfWidth, halfHeight, halfWidth, iconPaint); // 7
canvas.drawCircle(halfWidth, halfHeight, thirdWidth, clearPaint); // 8
- 其中 (1) 计算距离。
- (2) 在顶部画一个矩形
- (3) (4) 画两个圆清除矩形,使它看起来像两个圆弧
- 然后其余的调用以类似的方式绘制剩余的视图。
在 swift 上有什么等效或更好的方法?
如果它不是自定义视图,您可以使用 CAShape 层和 UIBezierPath 来执行此操作 // 如果它的自定义视图更容易,只需在绘图中创建路径并设置颜色,下面是您需要创建路径的一些方法和其他方法设置颜色等属性。如果不是自定义视图,您可以使用带有路径的 CAShapelayer 来实现相同的目的。
//create your path
let xpos: CGFloat = yourXpos // do your calculation and set the x and y
let ypos:cfFloat = yourYPos
let path = UIBezierPath() // UIBezierPath is like a pan you draw line arch circle, like pen you can move from one position to another, if you want to close(connected starting and end point) you just call close()
path.move(to: CGPoint(x: xpos, y: yPos)) //move is like the
path.addLine(to: CGPoint(x: xpos , y: yPos + 25))
path.addArc(withCenter: CGPoint(x: xpos + 1, y: yPos + 25), radius: 2, startAngle: 0, endAngle: CGFloat(Double.pi * 2), clockwise: true)
path.close()
path.move()//move to some new place
You have to calculate x,y like you already done for Android and just set the correct x and y values
//create shape layer and set the path you just created to the shapelayer and shapelayer to your view
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
self.yourView.layer.addSublayer(shapeLayer)
shapeLayer.lineWidth = 0.5 // setting the stoke width// thinkness of drawing
you can set the stroke colour or can fill it
shapeLayer.fillColor = UIColor.black.cgColor
shapeLayer.strokeColor = UIColor.green.cgColor
PS: I Haven't done the actual calculation but you have already done, so maybe with above help you can easly replicate for iOS.
我按照你的要求做了快速代码。希望对你有帮助。
//// Color Declarations
let color = UIColor(red: 0.387, green: 0.416, blue: 0.718, alpha: 1.000)
let color2 = UIColor(red: 1.000, green: 1.000, blue: 1.000, alpha: 1.000)
let color3 = UIColor(red: 1.000, green: 1.000, blue: 1.000, alpha: 1.000)
let color4 = UIColor(red: 0.300, green: 0.586, blue: 0.712, alpha: 1.000)
//// Oval Drawing
let ovalPath = UIBezierPath(ovalIn: CGRect(x: 41, y: 39, width: 20, height: 20))
color.setStroke()
ovalPath.lineWidth = 2.5
ovalPath.stroke()
//// Rectangle 2 Drawing
let rectangle2Path = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 100, height: 17))
color4.setFill()
rectangle2Path.fill()
//// Bezier 2 Drawing
let bezier2Path = UIBezierPath()
bezier2Path.move(to: CGPoint(x: -6.5, y: 18.5))
bezier2Path.addCurve(to: CGPoint(x: 41.76, y: 18.5), controlPoint1: CGPoint(x: 40.61, y: 18.5), controlPoint2: CGPoint(x: 41.76, y: 18.5))
bezier2Path.addCurve(to: CGPoint(x: 47.5, y: 22.7), controlPoint1: CGPoint(x: 41.76, y: 18.5), controlPoint2: CGPoint(x: 47.5, y: 18.5))
bezier2Path.addCurve(to: CGPoint(x: 47.5, y: 39.5), controlPoint1: CGPoint(x: 47.5, y: 26.9), controlPoint2: CGPoint(x: 47.5, y: 39.5))
color3.setStroke()
bezier2Path.lineWidth = 1
bezier2Path.stroke()
//// Bezier 3 Drawing
let bezier3Path = UIBezierPath()
bezier3Path.move(to: CGPoint(x: 100.5, y: 17.5))
bezier3Path.addCurve(to: CGPoint(x: 58.5, y: 17.5), controlPoint1: CGPoint(x: 59.5, y: 17.5), controlPoint2: CGPoint(x: 58.5, y: 17.5))
bezier3Path.addCurve(to: CGPoint(x: 55.5, y: 21.5), controlPoint1: CGPoint(x: 58.5, y: 17.5), controlPoint2: CGPoint(x: 55.5, y: 18.5))
bezier3Path.addCurve(to: CGPoint(x: 55.5, y: 39.5), controlPoint1: CGPoint(x: 55.5, y: 24.5), controlPoint2: CGPoint(x: 55.5, y: 39.5))
color2.setStroke()
bezier3Path.lineWidth = 1
bezier3Path.stroke()
//// Rectangle Drawing
let rectanglePath = UIBezierPath(rect: CGRect(x: 47, y: 59, width: 8, height: 41))
color.setFill()
rectanglePath.fill()
//
// 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)
}
}
这是我想到的第一个解决方案。可能需要一些调整,但这对我有用。我需要 UI 的 3 个阶段来放置在 UITableViewCell 中。 一个用于第一个单元格,一个用于最后一个单元格,另一个用于其余单元格。
结果是这样的