我遍历了一个UIBezierPaths数组以创建CALayer。生成CALayer的代码如下:
let layer = CAShapeLayer()
layer.path = path.cgPath
layer.strokeColor = UIColor.gray.cgColor
layer.fillColor = UIColor.clear.cgColor
layer.lineWidth = 3
layer.lineJoin = .bevel
return layer
返回每一层后,我将其添加到更大的层(shapeLayer
)中,然后将其添加到UIView
层中。 (希望这是有道理的。)
我遇到的麻烦是将在循环时添加的子层居中(在finalShape内部)。他们显然使用path.cgPath
设置了特定的路径,而我不知道如何在保持位置的同时实现这一目标。我真的(显然)对CALayers并不了解,无法解决此问题,我们将不胜感激。
谢谢。
-如果我向您展示完整的代码,可能会更有帮助
private let shapeLayer = CALayer()
func bind(shape: Shape) {
let data = NSKeyedUnarchiver.unarchiveObject(with: shape.strokeData)
guard let paths = data as? [UIBezierPath] else { return }
for path in paths {
let guideLine = drawPathLayer(for: path)
shapeLayer.addSublayer(guideLine)
}
layer.addSublayer(shapeLayer)
}
private func drawPathLayer(for path: UIBezierPath) -> CALayer {
let layer = CAShapeLayer()
layer.path = path.cgPath
layer.strokeColor = UIColor.gray.cgColor
layer.fillColor = UIColor.clear.cgColor
layer.lineWidth = 3
layer.lineJoin = .bevel
return layer
}
答案 0 :(得分:2)
如果要放置图层(或视图),则执行此操作的时间点至关重要。例如,如果您在viewDidLoad
中进行此操作,则为时过早,因为父层尚未具有其最终大小。而且,父层的大小可以更改,因此,只要父层的框架发生更改,最好将子层居中。您可以使用CALayer
的子类并覆盖layoutSublayers
来完成此操作。
它看起来像这样(不是正在运行的示例):
class CenteringLayer: CALayer {
override func layoutSublayers() {
super.layoutSublayers()
if let theSublayers = sublayers {
for s in theSublayers {
var theFrame = s.frame
theFrame.origin.x = (bounds.width - theFrame.width) / 2.0
theFrame.origin.y = (bounds.height - theFrame.height) / 2.0
s.frame = theFrame
}
}
}
}
注意:您的layer
还必须按
shapeLayer
shapeLayer.frame = layer.bounds
使此工作。您可以通过为CALayer
创建layer
的另一个子类并覆盖layoutSublayers()
来实现,或者(如果layer
是视图的层)覆盖layoutSubviews()
在您的视图类中。第三个选项可能是覆盖视图类中的layoutSublayers(of:)
,因为UIView始终是其层的委托。
但是,这些方法有点不太雅致,因此您最好考虑减少代码中的层数。例如您应尽量避免使用shapeLayer
。
如果所有路径都具有相同的属性,则由于连接层可能会占用大量资源,因此只能将一个CAShapeLayer
与串联路径一起使用。