调整 MenuBarExtra 窗口的大小

问题描述 投票:0回答:1

我正在开发具有

.window
风格的 MenuBarExtra。我知道我可以使用硬编码值或通过存储的变量来设置帧大小。

是否可以通过拖动边缘来调整窗口大小?

macos swiftui
1个回答
0
投票

我认为 SwiftUI 不支持这一点,所以你必须使用一些 AppKit API。

创建一个

NSViewRepresentable
,并访问自定义
window.styleMask
中的
NSView
属性。只需在其中插入
.resizable
标志即可,

struct Helper: NSViewRepresentable {
    
    class HelperView: NSView {
        override func viewWillMove(toWindow newWindow: NSWindow?) {
            super.viewWillMove(toWindow: newWindow)
            Task {
                newWindow?.styleMask.insert(.resizable)
            }
        }
    }
    
    func makeNSView(context: Context) -> HelperView {
        HelperView()
    }
    
    func updateNSView(_ nsView: HelperView, context: Context) {
    }
}
MenuBarExtra("Foo") {
    ZStack {
        Helper(width: $width, height: $height)
        Text("Bar")
            .padding()
            .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}
.menuBarExtraStyle(.window)

但是,关闭窗口后不会保留新的大小。如果你想这样做,那就有点复杂了。您需要为自定义

NSView
创建一种方法来告诉 SwiftUI 它已调整到什么大小。

这里我正在使用

didEndLiveResizeNotification
,并更新两个绑定,

struct Helper: NSViewRepresentable {
    @Binding var width: Double
    @Binding var height: Double
    
    class HelperView: NSView {
        var cancellable: AnyCancellable?
        var didChangeSize: ((CGSize) -> Void)?
        override func viewWillMove(toWindow newWindow: NSWindow?) {
            super.viewWillMove(toWindow: newWindow)
            Task {
                newWindow?.styleMask.insert(.resizable)
            }
            cancellable = NotificationCenter.default.publisher(for: NSWindow.didEndLiveResizeNotification, object: newWindow)
                .sink { [weak self] _ in
                    self?.didChangeSize?(newWindow?.contentView?.bounds.size ?? .zero)
                }
        }
    }
    
    func makeNSView(context: Context) -> HelperView {
        HelperView()
    }
    
    func updateNSView(_ nsView: HelperView, context: Context) {
        nsView.didChangeSize = {
            width = $0.width
            height = $0.height
        }
    }
}

然后你可以像这样使用它:

@State private var height: Double = 100
@State private var width: Double = 100

// ...

MenuBarExtra("Foo") {
    ZStack {
        Helper(width: $width, height: $height)
        Text("Bar")
            .padding()
            .frame(maxWidth: width, maxHeight: height)
    }
}
.menuBarExtraStyle(.window)
© www.soinside.com 2019 - 2024. All rights reserved.