CAShapeLayer не появляется - PullRequest
0 голосов
/ 27 декабря 2018

Я пытаюсь добавить CAShapeLayer к представлению.Но когда я добавляю customView к ViewCOntroller View, 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 Ответ

0 голосов
/ 27 декабря 2018

Я бы посоветовал:

  1. добавить свой подслой в init (чтобы он добавлялся один и только один раз);
  2. настроить его frame и path вlayoutSubviews (поэтому, если размер изменен, будь то из-за ограничений или другого механизма, слой будет обновляться соответствующим образом);
  3. при добавлении подпредставления / подслоя, размеры которого основаны на размере текущего представления, используйте ссылку 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
    }
}

Выход:

enter image description here


Или, если вы хотите использовать 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
    }
}
...