我正在尝试创建一个显示文档页面的NSScrollView。我添加了一个支持CALayer的NSView作为NSScrollView的documentView,然后我在documentView中添加了一个CALayer子图层。当我缩放NSScollview时,documentView正确放大和缩小。但是,documentView的子图层不会按其包含的documentView按比例缩放。如果我没有在documentView图层的子图层上设置autoresizingMask,则子图层会在缩放documentView时从屏幕上飞出。如果我使用LayerWidthSizable / LayerHeightSizable选项,子图层会比引用documentView超级图层时更大或更小。这是我到目前为止的代码:
这是NSScrollview:
class LayerScrollView: NSScrollView {
var containerLayer: ContainerLayer!
override func awakeFromNib() {
documentView = ContainerLayer(frame: frame)
}
}
这是ContainerLayer(documentView CALayer):
class ContainerLayer: NSView {
let documentLayer: DocumentLayer = DocumentLayer()
override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
autoresizesSubviews = true
wantsLayer = true
layer = CATiledLayer()
layer?.delegate = self
layer?.backgroundColor = NSColor.blueColor().CGColor
layer?.masksToBounds = true
documentLayer.frame = CGRect(x: frame.width / 4.0, y: frame.height / 4.0, width: frame.width / 2.0, height: frame.height / 2.0)
documentLayer.delegate = documentLayer
layer?.addSublayer(documentLayer)
documentLayer.autoresizingMask = CAAutoresizingMask.LayerWidthSizable | CAAutoresizingMask.LayerHeightSizable
documentLayer.setNeedsDisplay()
}
required init(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func drawLayer(layer: CALayer!, inContext ctx: CGContext!) {
CGContextSetFillColorWithColor(ctx, NSColor.redColor().CGColor)
CGContextFillRect(ctx, layer.bounds)
}
}
最后,这是DocumentLayer(DocumentLayer中包含的子层):
class DocumentLayer: CALayer {
override func drawLayer(layer: CALayer!, inContext ctx: CGContext!) {
CGContextSetFillColorWithColor(ctx, NSColor.redColor().CGColor)
CGContextFillRect(ctx, layer.bounds)
}
}
这是一张图片来说明问题和我想要的结果:
蓝色矩形是ContainerLayer,红色矩形是DocumentLayer。
我查看了大量的教程和文档,然后空了。看起来这应该是非常容易的。我在这里缺少什么?
答案 0 :(得分:1)
更新:已解决此问题
以下是解决方案,经过更长时间的挖掘文档和其他内容后发现(同样,感谢@mahaltertin建议我使用borderWidth来帮助调试):
LayerScrollView:
class LayerScrollView: NSScrollView {
var containerLayer: ContainerLayer!
override func awakeFromNib() {
containerLayer = ContainerLayer(frame: frame)
documentView = containerLayer
}
}
ContainerLayer:
class ContainerLayer: NSView {
let documentLayer: DocumentLayer = DocumentLayer()
override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
wantsLayer = true
layer = CALayer()
layer?.layoutManager = CAConstraintLayoutManager.layoutManager()
layer?.delegate = self
layer?.backgroundColor = NSColor.blueColor().CGColor
documentLayer.delegate = documentLayer
documentLayer.name = "documentLayer"
documentLayer.borderWidth = 1.0
documentLayer.backgroundColor = NSColor.redColor().CGColor
documentLayer.addConstraint(CAConstraint(attribute: CAConstraintAttribute.Width, relativeTo: "superlayer", attribute: CAConstraintAttribute.Width, scale: 0.5, offset: 0.0))
documentLayer.addConstraint(CAConstraint(attribute: CAConstraintAttribute.Height, relativeTo: "superlayer", attribute: CAConstraintAttribute.Height, scale: 0.5, offset: 0.0))
documentLayer.addConstraint(CAConstraint(attribute: CAConstraintAttribute.MidX, relativeTo: "superlayer", attribute: CAConstraintAttribute.MidX, scale: 1.0, offset: 0.0))
documentLayer.addConstraint(CAConstraint(attribute: CAConstraintAttribute.MidY, relativeTo: "superlayer", attribute: CAConstraintAttribute.MidY, scale: 1.0, offset: 0.0))
layer?.addSublayer(documentLayer)
layer?.setNeedsDisplay()
documentLayer.setNeedsDisplay()
}
required init(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
和DocumentLayer:
class DocumentLayer: CALayer {
override func actionForKey(event: String!) -> CAAction! {
return nil
}
}
解决方案是使用约束。 DocumentLayer中的actionForKey方法的覆盖是为了防止DocumentLayer在缩放时进行动画处理。 ContainerLayer中定义的约束指定DocumentLayer应该是ContainerLayer的宽度/高度的一半,并且两个层的中间应该相同。缩放现在可以保持比例正确。