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)
...
}
我真的不明白这是怎么回事。请帮忙!
我建议:
- 在
init
中添加您的子层(因此它只添加一次);
- 在
layoutSubviews
中配置其 frame
和 path
(因此,如果调整大小,无论是通过约束还是其他机制,图层都会相应更新);
- 添加尺寸基于当前视图大小的 subview/sublayer 时,参考视图的
bounds
(当前视图中的坐标系),而不是 frame
也不是center
(都在父视图的坐标系中);和
- 使用
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
}
}
我正在尝试向视图添加 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)
...
}
我真的不明白这是怎么回事。请帮忙!
我建议:
- 在
init
中添加您的子层(因此它只添加一次); - 在
layoutSubviews
中配置其frame
和path
(因此,如果调整大小,无论是通过约束还是其他机制,图层都会相应更新); - 添加尺寸基于当前视图大小的 subview/sublayer 时,参考视图的
bounds
(当前视图中的坐标系),而不是frame
也不是center
(都在父视图的坐标系中);和 - 使用
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
}
}