CAShapeLayer未显示在屏幕上

时间:2018-12-31 15:14:15

标签: ios swift uibezierpath

我有一个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)
        }
    }
}

它应该为每条路线指示画一条线,以火车线名的颜色表示。在两条线相遇的地方,应该有一个连接器斑点,如伦敦地铁图所示。

1 个答案:

答案 0 :(得分:1)

cellForItemAt中,将routineOutline设置为RouteOverview。因此,您要保存对自定义视图的引用,但是在任何时候都看不到将RouteOverview添加到视图层次结构。 (您正在向RouteOverview添加形状图层,但从未添加RouteOverview本身。)您有时需要调用addSubview