-
Work with windows in SwiftUI
Learn how to create great single and multi-window apps in visionOS, macOS, and iPadOS. Discover tools that let you programmatically open and close windows, adjust position and size, and even replace one window with another. We'll also explore design principles for windows that help people use your app within their workflows.
Capítulos
- 0:00 - Introduction
- 1:19 - Fundamentals
- 6:15 - Placement
- 9:43 - Sizing
- 12:03 - Next steps
Recursos
Videos relacionados
WWDC24
WWDC23
-
Buscar este video…
-
-
2:36 - BOT-anist scenes
@main struct BOTanistApp: App { var body: some Scene { WindowGroup(id: "editor") { EditorContentView() } WindowGroup(id: "game") { GameContentView() } .windowStyle(.volumetric) } } -
3:09 - Creating the movie WindowGroup
@main struct BOTanistApp: App { var body: some Scene { WindowGroup(id: "editor") { EditorContentView() } WindowGroup(id: "game") { GameContentView() } .windowStyle(.volumetric) WindowGroup(id: "movie") { MovieContentView() } } } -
3:55 - Opening a movie window
struct EditorContentView: View { @Environment(\.openWindow) private var openWindow var body: some View { Button("Open Movie", systemImage: "tv") { openWindow(id: "movie") } } } -
4:45 - Pushing a movie window
struct EditorContentView: View { @Environment(\.pushWindow) private var pushWindow var body: some View { Button("Open Movie", systemImage: "tv") { pushWindow(id: "movie") } } } -
5:34 - Toolbar
CanvasView() .toolbar { ToolbarItem { Button(...) } ... } -
5:40 - Title menu
CanvasView() .toolbar { ToolbarTitleMenu { Button(...) } ... } -
5:48 - Hiding window controls
WindowGroup(id: "movie") { ... } .persistentSystemOverlays(.hidden) -
6:28 - Creating the controller window
@main struct BOTanistApp: App { var body: some Scene { ... WindowGroup(id: "movie") { MovieContentView() } WindowGroup(id: "controller") { ControllerContentView() } } } -
6:34 - Opening the controller window
struct GameContentView: View { @Environment(\.openWindow) private var openWindow var body: some View { ... Button("Open Controller", systemImage: "gamecontroller.fill") { openWindow(id: "controller") } } } -
7:46 - Positioning the controller window
WindowGroup(id: "controller") { ControllerContentView() } .defaultWindowPlacement { content, context in #if os(visionOS) return WindowPlacement(.utilityPanel) #elseif os(macOS) ... #endif } -
8:45 - Positioning the controller window continued
WindowGroup(id: "controller") { ControllerContentView() } .defaultWindowPlacement { content, context in #if os(visionOS) return WindowPlacement(.utilityPanel) #elseif os(macOS) let displayBounds = context.defaultDisplay.visibleRect let size = content.sizeThatFits(.unspecified) let position = CGPoint( x: displayBounds.midX - (size.width / 2), y: displayBounds.maxY - size.height - 20 ) return WindowPlacement(position, size: size) #endif } -
10:12 - Default size
@main struct BOTanistApp: App { var body: some Scene { ... WindowGroup(id: "movie") { MovieContentView() } .defaultSize(width: 1166, height: 680) } } -
10:49 - Setting resize limits on the movie window
@main struct BOTanistApp: App { var body: some Scene { ... WindowGroup(id: "movie") { MovieContentView() .frame( minWidth: 680, maxWidth: 2720, minHeight: 680, maxHeight: 1020 ) } .windowResizability(.contentSize) } } -
11:37 - Controller window resizability
@main struct BOTanistApp: App { var body: some Scene { ... WindowGroup(id: "controller") { ControllerContentView() } .windowResizability(.contentSize) } }
-