swift 调整包含NavigationSplitView的窗口大小

zphenhs4  于 2022-12-10  发布在  Swift
关注(0)|答案(1)|浏览(173)

我正在使用SwiftUI构建一个macOS 13应用程序。该应用程序使用NavigationSplitView提供两列导航,它提供了一个侧边栏和一个细节视图。细节视图的大小不同,所以我希望窗口根据每个细节视图的大小来改变大小。
在下面的示例中,详细视图为AppleViewKiwiViewPeachViewAppleView的大小为400x300,KiwiView的大小为300x200。当我运行应用程序时,当详细视图改变时,窗口不会调整其大小。我试图将导航视图 Package 在VStack中,但没有帮助。有人知道如何让应用程序的窗口根据所选的详细视图调整大小吗?

import SwiftUI

struct AppleView: View {
    var body: some View {
        Text("Apple View 🍎")
            .font(.title)
            .frame(width: 400, height: 300)
            .background(.red)
    }
}

struct KiwiView: View {
    var body: some View {
        Text("Kiwi View 🥝")
            .font(.title)
            .frame(width: 300, height: 200)
            .background(.green)
    }
}

struct PeachView: View {
    var body: some View {
        Text("Peach View 🍑")
            .font(.title)
            .background(.pink)
    }
}

enum Fruit: String, CaseIterable {
    case apple = "Apple"
    case kiwi = "Kiwi"
    case peach = "Peach"
}

struct ContentView: View {
    
    @State private var selectedFruit: Fruit = .apple
    
    var body: some View {
        NavigationSplitView {
            List(Fruit.allCases, id: \.self, selection: $selectedFruit) { fruit in
                Text(fruit.rawValue)
            }
        } detail: {
            switch selectedFruit {
            case .apple:
                AppleView()
            case .kiwi:
                KiwiView()
            case .peach:
                PeachView()
            }
        }
    }
}

我也试过设置主窗口组的.windowResizability(),但没有解决这个问题。

import SwiftUI

@main
struct ExampleApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .windowResizability(.contentSize)
    }
}
gr8qqesn

gr8qqesn1#

很抱歉,回复太晚了。它同样适用于NavigationSplitView。由于您希望具有固定的大小,我将向所有子视图添加帧以实现一致的行为,因此在本例中,PeachViewList
然后只需相应地修改ContentView

struct ContentView: View {
    
    @State private var selectedFruit: Fruit = .apple
    @State private var window: NSWindow?
    
    var body: some View {
        NavigationSplitView {
            List(Fruit.allCases, id: \.self, selection: $selectedFruit) { fruit in
                Text(fruit.rawValue)
            }
            .frame(width: 100)
        } detail: {
            switch selectedFruit {
            case .apple:
                AppleView()
            case .kiwi:
                KiwiView()
            case .peach:
                PeachView()
            }
        }
        .background(WindowAccessor(window: $window))
        .onChange(of: selectedFruit) { newValue in
            if newValue == .apple {
                window?.setFrame(NSRect(x: 600, y: 400, width: 500, height: 600), display: true)
            } else if newValue == .kiwi {
                window?.setFrame(NSRect(x: 600, y: 400, width: 400, height: 500), display: true)
            } else if newValue == .peach {
                window?.setFrame(NSRect(x: 600, y: 400, width: 350, height: 400), display: true)
            }
        }
    }
}

然后添加WindowAccessor

struct WindowAccessor: NSViewRepresentable {
    @Binding var window: NSWindow?

    func makeNSView(context: Context) -> NSView {
        let view = NSView()
        DispatchQueue.main.async {
            self.window = view.window
        }
        return view
    }

    func updateNSView(_ nsView: NSView, context: Context) {}
}

要在整个应用程序中完全访问窗口,您可能还需要考虑使用App/Scene Delegate进行访问,如here所述

相关问题