NSWindow - 调整大小时缩放所有内容

NSWindow - scale all content when resizing

我不知道如何完成这个看起来很简单的任务。我有一个 macOS cocoa 应用程序,它由一个 window 组成,里面有一个自定义视图。视图是 600x500 点。在这个视图中是一个子视图,它横跨主视图的整个宽度,但只占视图高度的一小部分。它的垂直原点大约在 y=200。

子视图从距左右边界 20 点开始绘制一个矩形,高度约为 30 点。它还将其层与 CAEmitter 层一起用作子层。该发射器的位置可由用户控制,因此其位置将通过从视图外部调用的函数进行更新。

我想要的:

当用户调整 window 的大小时,它应该只按比例缩放(我设法做到了),以便 window 的内容作为一个整体得到调整。任何子视图都不应该以任何方式重新排列,它们都应该保持它们的大小和相对于彼此的位置,只是得到 bigger/smaller.

我无法使用它。

到目前为止我尝试过的:

cocoa 框架中关于大小、锚点、约束等的切入点太多,我根本不知道从哪里开始,所以任何帮助将不胜感激。

更新:我将代码精简到最小值:

class MyViewController: NSViewController {

    public init () {
        super.init(nibName: nil, bundle: nil)
        self.view = MyView(frame: NSRect(x: 0, y: 0, width: 600, height: 500))
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

class MyView: NSView {

    override init(frame frameRect: NSRect) {
    
        super.init(frame: frameRect)
    
        let subView = MySubView(frame: NSRect(x: 0, y: frame.height/3, width: frame.width, height: frame.height/10))
        self.addSubview(subView)
        subView.autoresizingMask = [.width, .height]
        subView.translatesAutoresizingMaskIntoConstraints = true
        subView.trailingAnchor.constraint(greaterThanOrEqualTo: self.trailingAnchor).isActive = true
        subView.leadingAnchor.constraint(greaterThanOrEqualTo: self.leadingAnchor).isActive = true
    }

    required init?(coder decoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}


class MySubView: NSView {

    override func draw(_ dirtyRect: NSRect) {
    
        let context = NSGraphicsContext.current!.cgContext
        context.setStrokeColor(.black)
        context.setFillColor(CGColor.init(red: 0.7, green: 0.7, blue: 0.7, alpha: 1))
        context.setLineWidth(2)
    
        let borderRect = CGRect(x: constant.sideMargin, y: 5, width: frame.width-2*constant.sideMargin, height: frame.height-10)
        let roundedRect = CGPath.init(roundedRect: borderRect, cornerWidth: 5, cornerHeight: 5, transform: nil)
    
        context.addPath(roundedRect)
        context.fillPath()
        context.strokePath()
    
        context.addPath(roundedRect)
        context.strokePath()
    } 
}

View Programming Guide 中所述,如果 boundsframe 不同,NSView 将缩放和偏移其内容。只需在 frame 更改时将 bounds 设置为 {600, 500}。视图的子视图不需要约束,因为它们的坐标不会改变。

MyView 设置代码:

// frame changed notitication
self.postsFrameChangedNotifications = true
self.frameChangeObserver = NotificationCenter.default.addObserver(forName: NSView.frameDidChangeNotification,
    object: self, queue: OperationQueue.main) { (note) in
    self.setBoundsSize(NSSize(width:600, height: 500))
}

let subView = MySubView(frame: NSRect(x: 0, y: bounds.height/3, width: bounds.width, height: bounds.height/10))
// no constraints
subView.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(subView)