ios - CAShapeLayer 未显示在屏幕上
问题描述
我UICollectionViewCell
有一个里面有一个 UIView 的。将单元格出列时,我使用必要的数据对其进行初始化。初始化数据后,在 内部UIView
,有一些要显示的图形。然而,什么也没有出现。
最初,这都是在UICollectionView
cellForItemAt
方法内部并画线,但它应该在 UIView 内部,所以我将它子类化并将代码放在那里。这是它停止工作的地方。
我尝试过覆盖 draw 方法,使用 init 内部的绘图调用我的方法,然后从单元格中调用它们。我得到控制台中显示的打印语句,但屏幕上没有绘图。
extension ChooseRouteViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Route", for: indexPath) as! PotentialRouteCell
cell.routeOutline = RouteOverview(frame: CGRect(x: 73 + 4, y: 8, width: (cell.bounds.width - 83), height: 98), route: instructions)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: possibleRouteCollectionView.bounds.width - 40, height: 150)
}
}
class RouteOverview: UIView {
init(frame: CGRect, route: [Instruction]) {
super.init(frame: frame)
getOutline(from: route)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private struct Overview {
let fromStation: Station
let toStation: Station
let lineName: String
init(from: Station, to: Station, line: String) {
self.fromStation = from
self.toStation = to
self.lineName = line
}
}
private var overview: [Overview] = []
private var keyStations: [String] = []
private var linesToDraw: Int = 0
private var linesDrawn: [CAShapeLayer] = []
private var lineX: CGFloat = 24.0
private var lineY: CGFloat {
return self.bounds.height / 2
}
private var lineLength: CGFloat {
return (self.bounds.width - 48) / CGFloat(overview.count)
}
private func getOutline(from route: [Instruction]) {
for instruction in route {
if instruction.type == .route {
let instructionOverview = Overview(from: instruction.route.first!.station, to: instruction.route.last!.station, line: instruction.line)
overview.append(instructionOverview)
}
}
linesToDraw = overview.count
print("\n Debug: There are \(linesToDraw) lines to draw. Each line is \(lineLength) points long.")
drawLine(fromPoint: CGPoint(x: lineX, y: lineY), toPoint: CGPoint(x: lineX + lineLength, y: lineY), lineName: overview[linesDrawn.count].lineName)
}
private func drawLine(fromPoint start: CGPoint, toPoint end: CGPoint, lineName: String) {
lineX += lineLength
let line = CAShapeLayer()
let path = UIBezierPath()
path.move(to: start)
path.addLine(to: end)
line.lineWidth = 8
line.lineCap = .round
line.strokeColor = UIColor(named: lineName)!.cgColor
line.fillColor = UIColor(named: lineName)!.cgColor
line.path = path.cgPath
self.layer.insertSublayer(line, at: 0)
linesDrawn.append(line)
linesToDraw -= 1
if linesToDraw >= 0 {
addDetail(at: end, lineName: lineName)
}
}
func addDetail(at point: CGPoint, lineName: String) {
if linesToDraw != 0 {
let circle = CAShapeLayer()
let path = UIBezierPath(arcCenter: point, radius: 8, startAngle: 0, endAngle: CGFloat(Double.pi * 2), clockwise: true)
circle.lineWidth = 6
circle.strokeColor = UIColor.black.cgColor
circle.fillColor = UIColor.black.cgColor
circle.path = path.cgPath
let innerCircle = CAShapeLayer()
let innerPath = UIBezierPath(arcCenter: point, radius: 4, startAngle: 0, endAngle: CGFloat(Double.pi * 2), clockwise: true)
innerCircle.lineWidth = 6
innerCircle.strokeColor = UIColor.white.cgColor
innerCircle.fillColor = UIColor.white.cgColor
innerCircle.path = innerPath.cgPath
self.layer.addSublayer(circle)
self.layer.insertSublayer(innerCircle, above: circle)
}
let lineNameLabel = RoundLabel(frame: CGRect(x: point.x - (lineLength / 2) - 18, y: point.y + 16, width: 40, height: 24))
lineNameLabel.cornerRadius = 5.0
lineNameLabel.text = String(lineName.prefix(3))
lineNameLabel.textAlignment = .center
lineNameLabel.font = UIFont(name: "London Tube", size: 15.0)
lineNameLabel.backgroundColor = UIColor(named: lineName)!
lineNameLabel.textColor = .white
lineNameLabel.clipsToBounds = true
self.addSubview(lineNameLabel)
self.setNeedsLayout()
self.setNeedsDisplay()
if linesToDraw >= 1 {
drawLine(fromPoint: CGPoint(x: point.x, y: lineY), toPoint: CGPoint(x: point.x + lineLength, y: lineY), lineName: overview[linesDrawn.count].lineName)
}
}
}
它应该为每条路线指令画一条线,以火车线路名称的颜色。在两条线相交的地方,应该有一个连接器斑点,如伦敦地铁地图上所示。绘制的线还应该有一个缩写的火车线名称标签。
解决方案
在cellForItemAt
你设置routineOutline
为你的RouteOverview
. 因此,您正在保存对自定义视图的引用,但我看不到您RouteOverview
在任何时候都将其添加到视图层次结构中。(您正在向 中添加形状图层RouteOverview
,但从不添加RouteOverview
本身。)您需要addSubview
在某个时候调用。
推荐阅读
- javascript - SPARX 企业架构师。使用脚本为带有格式化文本的图表添加注释
- python-3.x - 使用python根据学生的百分比识别学生的详细信息
- angular - 单元测试中可观察的角度未覆盖线:
- sql - Oracle(SQL 语句)- 将 CASE 与 WHERE CLAUSE 结合使用
- python - 哪种过滤器更好更快
- java-native-interface - 调用打包在 jar 文件中的本机方法时出现 UnsatisfiedLinkError
- swift - Apple 地图显示自定义引脚详细信息和始终打开模式
- php - 在 MySQL 准备语句中将 2+ 数组绑定为参数的解决方案?
- vba - 自动将个别成员的姓名和金额插入消息正文,并以短信形式发送到相应号码
- c# - 如何让 WPF DataGrid 定制错误样式适用于值转换器错误?