我正在尝试制作一个显示文档页面的 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 宽度/高度的一半,并且两个层的中间应该相同。现在缩放可以保持比例正确。

10-08 12:28