我正在尝试制作一个显示文档页面的 NSScrollView。我添加了一个 CALayer-backed NSView 作为 NSScrollView 的 documentView,然后我添加了一个 CALayer 子层到 documentView。当我缩放 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。
我浏览了许多教程和文档,结果是空的。看起来这应该是非常容易做到的。我在这里缺少什么?
最佳答案
更新:已解决
这是解决方案,经过更多小时的文档和其他内容的挖掘后发现(另外,感谢@mahaltertin 建议我使用 borderWidth 来帮助调试):
层滚动 View :
class LayerScrollView: NSScrollView {
var containerLayer: ContainerLayer!
override func awakeFromNib() {
containerLayer = ContainerLayer(frame: frame)
documentView = 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")
}
}
和文档层:
class DocumentLayer: CALayer {
override func actionForKey(event: String!) -> CAAction! {
return nil
}
}
解决方案是使用约束。覆盖 DocumentLayer 中的 actionForKey 方法是为了防止 DocumentLayer 在缩放时进行动画处理。 ContainerLayer 中定义的约束指定 DocumentLayer 应该是 ContainerLayer 宽度/高度的一半,并且两个层的中间应该相同。现在缩放可以保持比例正确。