【问题标题】:NSWindow - scale all content when resizingNSWindow - 调整大小时缩放所有内容
【发布时间】:2022-01-02 04:41:50
【问题描述】:

我无法弄清楚如何完成看似非常简单的任务。我有一个 macOS 可可应用程序,它由一个带有自定义视图的窗口组成。视图为 600x500 点。在这个视图内部是一个子视图,它跨越了主视图的整个宽度,但只是视图高度的一小部分。它的垂直原点大约在 y=200。

子视图从左右边界开始 20 点开始绘制一个矩形,高度约为 30 点。它还使用它的层和一个 CAEmitter 层作为子层。这个发射器的位置可以由用户控制,因此它的位置将由从视图外部调用的函数更新。

我想要什么:

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

我没有让这个工作。

到目前为止我所尝试的:

  • 如果没有设置其他属性,我可以调整窗口大小,但是 subiew 根本不缩放,它坚持它在 监督。
  • 我为 trailingAnchor 设置了subView.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor).isActive = true 和相同的设置,另外我设置了subView.autoresizingMask = [.width] 现在子视图中绘制的矩形的宽度得到了调整,但矩形的边缘远离边界 20 个点。我也想缩放这个距离。
  • 矩形的高度保持不变。当我将-heigth 添加到子视图的自动调整大小蒙版时,高度会以一种非常不成比例的方式扭曲(到顶部和底部边距的距离保持不变,因此虽然子视图的高度在开始时只有大约 30,但矩形在调整大小时会被炸毁.
  • 发射器未重新定位。它的水平位置是根据用户交互计算的,并且是相对于视图的边框,在调整大小后它会保持在其绝对位置。我通过调用 draw() 方法的计算函数解决了这个问题,但这对我来说似乎不正确

在 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()
    } 
}

【问题讨论】:

  • setBoundsSize 是您要找的吗?
  • 提示:如果translatesAutoresizingMaskIntoConstraints 未关闭,autoresizingMask 将转换为约束。 Xcode 可以在运行时显示视图和约束。
  • 说实话,我还是没有头绪。我在精简版本中添加了我的代码。在 AppDelegate 中,我将窗口设置为固定的纵横比。调整窗口大小时,子视图内容(矩形)的左右边缘跟随边框,但即使这不是我想要的。它应该保持它的相对距离,所以边距应该变大一点。矩形的上边距似乎固定在视图的中心,而不是停留在高度的 ⅓。我迷路了!!!

标签: swift cocoa resize nsview


【解决方案1】:

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)

【讨论】:

  • 非常感谢。我知道解决方案应该不会太复杂,但我从来没有想过我必须设置回调。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-18
  • 2015-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多