我正在使用SwiftUI开发新的macOS应用程序,但无法弄清楚如何定义窗口大小。在AppDelegate中,窗口大小定义如下:
// --- AppDelegate.swift ---
import Cocoa
import SwiftUI
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
var window: NSWindow!
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
window = NSWindow(
contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
backing: .buffered, defer: false)
window.center()
window.setFrameAutosaveName("Main Window")
window.contentView = NSHostingView(rootView: ContentView())
window.makeKeyAndOrderFront(nil)
}
}
ContentView的定义如下:
// --- ContentView.swift ---
import SwiftUI
struct ContentView : View {
var body: some View {
VStack {
Spacer()
Text("Top Text")
Spacer()
Text("Bottom Text")
Spacer()
}
}
}
当我构建并运行该应用程序时,会出现一个窗口,但它的大小不正确。它显示为大约两个文本标签的大小,而不是AppDelegate中定义的480x300大小。
使用SwiftUI时,我应该如何为Mac应用程序定义窗口大小?
答案 0 :(得分:3)
我是这样做的。它具有启动大小并且可调整大小。
struct windowSize {
let minWidth : CGFloat = 100
let minHeight : CGFloat = 200
let maxWidth : CGFloat = 200
let maxHeight : CGFloat = 250
}
struct ContentView : View {
var body: some View {
Group() {
VStack {
Text("Hot Stuff")
.border(Color.red, width: 1)
Text("Hot Chocolate")
.border(Color.red, width: 1)
}
}
.frame(minWidth: windowSize().minWidth, minHeight: windowSize().minHeight)
.frame(maxWidth: windowSize().maxWidth, maxHeight: windowSize().maxHeight)
.border(Color.blue, width: 1)
}
}
答案 1 :(得分:1)
有时,这种行为可能会令人困惑。这是因为一旦至少运行一次应用程序,然后再手动调整窗口大小和位置,则委托中指定的大小将不再重要。
应用程序会记住用户何时调整窗口大小,并使用键“ NSWindow Frame Main Window” 下的UserDefaults中存储的信息。如果您想重置它,则需要使用默认值命令将其清除。
现在,这已经不合时宜了,您的窗口如此狭窄的原因如下:
使用SwiftUI时,并非所有视图都创建相同。例如:Text()很谦虚。它只会占用所需的空间。而诸如Spacer()之类的其他视图将扩大其父母提供的范围(我称它们为贪婪)。
在您的情况下,您有一个带Stackr()的VStack。这意味着VStack填充将扩展为填充其父级提供的高度。在这种情况下,代表需要300点(或存储在UserDefaults中的任何内容)。
另一方面,由于HStack中没有任何Spacer(),因此ContentView将仅水平扩展至所需的水平。也就是说,与最宽的Text()视图一样宽。如果在VStack中添加HStack { Spacer() }
,则内容视图 将扩展为占据委托中指定的480 pt(或存储在UserDefaults中的任何内容)。无需设置frame()。
另一种方法(为ContentView指定框架)基本上是告诉ContentView不管是什么,都为480x300。实际上,如果这样做,将无法调整窗口大小!
所以现在您知道了,我认为这很清楚...但是,这对您可能非常有用:
还有另一个贪婪的视图可以帮助您调试窗口大小:GeometryReader。此视图将始终采用所提供的视图。运行此示例,您将确切知道在应用启动时提供了多少空间:
struct ContentView : View {
var body: some View {
GeometryReader { geometry in
VStack {
Text("\(geometry.size.width) x \(geometry.size.height)")
}.frame(width: geometry.size.width, height: geometry.size.height)
}
}
}
我写了一篇有关 GeometryReader 的文章,我建议您查看一下:https://swiftui-lab.com/geometryreader-to-the-rescue/
顺便说一句,我的 AppDelegate 看起来像这样:
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
window = NSWindow(
contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
backing: .buffered, defer: false)
window.center()
window.setFrameAutosaveName("Main Window")
window.contentView = NSHostingView(rootView: ContentView())
window.makeKeyAndOrderFront(nil)
}
从Beta3开始,新项目的初始ContentView使用maxWidth和maxHeight。切肉刀的替代品。
struct ContentView : View {
var body: some View {
Text("Hello World")
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}