CAShapeLayer 不显示

CAShapeLayer doesn't show up

我正在尝试向视图添加 CAShapeLayer。但是当我将 customView 添加到 ViewCOntroller 的视图时,shapeLayer 没有出现。捕获层次结构显示该层甚至没有插入到视图中。这是代码:

override class var layerClass: AnyClass {
        return CAShapeLayer.self
    }
...

override func didMoveToSuperview() {
        let diameter = min(self.frame.width, self.frame.height)
        let path = UIBezierPath(arcCenter: self.center, radius: diameter/2, startAngle: 0, endAngle: CGFloat.pi*2, clockwise: true)
        let sLayer = CAShapeLayer()
        sLayer.frame = bounds
        sLayer.path = path.cgPath
        sLayer.fillMode = .backwards
        sLayer.fillColor = UIColor.blue.cgColor//bubbleColor?.cgColor
        layer.addSublayer(sLayer)
    }

并且在 ViewController 中:

override func viewDidLoad() {
        super.viewDidLoad()
        let node = Node(frame: CGRect(origin: self.view.center, size: CGSize(width: 250, height: 250)))
        self.view.addSubview(node)
...
}

我真的不明白这是怎么回事。请帮忙!

我建议:

  1. init 中添加您的子层(因此它只添加一次);
  2. layoutSubviews 中配置其 framepath(因此,如果调整大小,无论是通过约束还是其他机制,图层都会相应更新);
  3. 添加尺寸基于当前视图大小的 subview/sublayer 时,参考视图的 bounds(当前视图中的坐标系),而不是 frame也不是center(都在父视图的坐标系中);和
  4. 使用 addSublayer 方法或 layerClass 方法,但不能同时使用。

因此,添加 CAShapeLayer 作为子层:

@IBDesignable
class CircleView: UIView {
    @IBInspectable var bubbleColor: UIColor = .blue { didSet { shapeLayer.fillColor = bubbleColor.cgColor } }

    private lazy var shapeLayer: CAShapeLayer = {
        let sLayer = CAShapeLayer()
        sLayer.fillColor = bubbleColor.cgColor
        return sLayer
    }()

    override init(frame: CGRect = .zero) {
        super.init(frame: frame)
        configure()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        configure()
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        shapeLayer.frame = bounds
        updatePath()
    }
}

// MARK: - Utility methods

private extension CircleView {
    func configure() {
        layer.addSublayer(shapeLayer)
    }

    func updatePath() {
        let diameter = min(bounds.width, bounds.height)
        let arcCenter = CGPoint(x: bounds.midX, y: bounds.midY)
        shapeLayer.path = UIBezierPath(arcCenter: arcCenter, radius: diameter / 2, startAngle: 0, endAngle: .pi * 2, clockwise: true).cgPath
    }
}

产量:


或者,如果您想使用 layerClass 方法:

@IBDesignable
class CircleView: UIView {
    @IBInspectable var bubbleColor: UIColor = .blue { didSet { shapeLayer.fillColor = bubbleColor.cgColor } }

    override class var layerClass: AnyClass { return CAShapeLayer.self }

    private var shapeLayer: CAShapeLayer { return layer as! CAShapeLayer}

    override init(frame: CGRect = .zero) {
        super.init(frame: frame)
        configure()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        configure()
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        updatePath()
    }
}

// MARK: - Utility methods

private extension CircleView {
    func configure() {
        shapeLayer.fillColor = bubbleColor.cgColor
    }

    func updatePath() {
        let diameter = min(bounds.width, bounds.height)
        let arcCenter = CGPoint(x: bounds.midX, y: bounds.midY)
        shapeLayer.path = UIBezierPath(arcCenter: arcCenter, radius: diameter / 2, startAngle: 0, endAngle: .pi * 2, clockwise: true).cgPath
    }
}