在 macOS 上的 SwiftUI 应用中,如何隐藏标题栏

8

如何在新的SwiftUI App协议中隐藏标题栏?

由于AppDelegate.swift和SceneDelegate.swift协议已经消失,我不能再遵循这份文档了: https://developer.apple.com/documentation/uikit/mac_catalyst/removing_the_title_bar_in_your_mac_app_built_with_mac_catalyst

我无法实现这段代码:

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?    
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = (scene as? UIWindowScene) else { return }
        #if targetEnvironment(macCatalyst)
        if let titlebar = windowScene.titlebar {
            titlebar.titleVisibility = .hidden
            titlebar.toolbar = nil
        }
        #endif
    }
}

希望新的AppProtocol仍然可行。谢谢提前。

2
您可以使用 withHostingWindow(来自 https://dev59.com/EFIG5IYBdhLWcg3wtjy2#63276688)来查找自己的窗口,然后执行所需操作。 - Asperi
@Asperi,感谢您的回复,多亏了您的答案,我成功隐藏了标题栏。我会发布这个答案,但我仍然希望苹果能尽快提供官方支持。 - John
2个回答

14

以下是如何隐藏标题栏的方法:

struct ContentView: View {
    var body: some View {
        ZStack {
            Text("Example UI")
        }
        .withHostingWindow { window in
            #if targetEnvironment(macCatalyst)
            if let titlebar = window?.windowScene?.titlebar {
                titlebar.titleVisibility = .hidden
                titlebar.toolbar = nil
            }
            #endif
        }
    }
}

extension View {
    fileprivate func withHostingWindow(_ callback: @escaping (UIWindow?) -> Void) -> some View {
        self.background(HostingWindowFinder(callback: callback))
    }
}

fileprivate struct HostingWindowFinder: UIViewRepresentable {
    var callback: (UIWindow?) -> ()

    func makeUIView(context: Context) -> UIView {
        let view = UIView()
        DispatchQueue.main.async { [weak view] in
            self.callback(view?.window)
        }
        return view
    }

    func updateUIView(_ uiView: UIView, context: Context) {
    }
}

UIKit是我们的一切! :D - imike
@imike 是的,我期待着 SwiftUI 将来拥有一切的时刻 :) - John
更好的方法是创建UIView的子类,并实现它的willMove:toWindow:,在那里调用回调函数,跳过异步操作。这种方法没有闪烁,当视图出现时,标题栏立即隐藏。 - Jaka Jančar
我将.withHostingWindow修改器中的if let titlebar条件语句直接添加到了我的AppDelegate的didFinishLaunchingWithOptions方法中,它完美地工作了! - dbDev

1
在您的场景中,将.windowStyle(_ :)设置为HiddenTitleBarWindowStyle()。
@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .windowStyle(HiddenTitleBarWindowStyle())
    }
}

编辑:糟糕。虽然根据在线文档,这个API应该适用于Mac Catalyst,但是看起来它实际上没有在框架中标记,所以你不能使用它。


我该如何进入一个场景? - John
通常在@main中创建场景,例如WindowGroup。因此,在WindowGroup上设置windowStyle。 - Adam
我尝试过了,但是没有这个选项。 - John
啊,抱歉,在线文档上说windowStyle(_:)可用于Mac Catalyst,但实际上并不是这样。希望苹果能够添加它! - Adam
没问题!我希望它能够实现,因为这样可以让你的应用程序看起来更好。 - John
在 macOS 11 上运行得非常好。谢谢。 - XY Li

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接