如何使用 SwiftUI 向 macOS 应用程序添加工具栏?

Bij*_*raj 15 macos swiftui macos-catalina

我正在尝试使用 SwiftUI 将标题栏中的工具栏添加到 macOS 应用程序,类似于下面显示的内容。

macOS 应用程序标题栏中的工具栏

我无法找到使用 SwiftUI 实现此目的的方法。目前,我的视图中有我的工具栏(只有一个文本字段),但我想将它移到标题栏中。

我目前的代码:

struct TestView: View {
    var body: some View {
        VStack {
            TextField("Placeholder", text: .constant("")).padding()
            Spacer()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,就我而言,我需要在工具栏内放置文本字段。

小智 16

从 macOS 11 开始,您可能希望使用WWDC Session 10104 中记录的新 API 作为新标准。WWDC Session 10041在 12 分钟处提供了明确的代码示例。

NSWindowToolbarStyle.unified
Run Code Online (Sandbox Code Playgroud)

或者

NSWindowToolbarStyle.unifiedCompact
Run Code Online (Sandbox Code Playgroud)

在 SwiftUI 中,您可以使用新的.toolbar { }构建器。

struct ContentView: View {


  var body: some View {
        List {
            Text("Book List")
        }
        .toolbar {
            Button(action: recordProgress) {
                Label("Record Progress", systemImage: "book.circle")
            }
        }
    }

    private func recordProgress() {}
}
Run Code Online (Sandbox Code Playgroud)

  • @Nooneyouknow ,如果您使用 ToolbarItem 的showsByDefault 参数,您可以在 SwiftUI 中拥有可自定义的工具栏。 (2认同)

Bij*_*raj 7

方法一:

这是通过添加标题栏附件来完成的。我能够通过修改 AppDelegate.swift 文件来完成这项工作。我不得不应用一些奇怪的填充以使其看起来正确。

AppDelegate.swift

func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Create the SwiftUI view that provides the window contents.
        let contentView = ContentView()

        // Create the titlebar accessory
        let titlebarAccessoryView = TitlebarAccessory().padding([.top, .leading, .trailing], 16.0).padding(.bottom,-8.0).edgesIgnoringSafeArea(.top)

        let accessoryHostingView = NSHostingView(rootView:titlebarAccessoryView)
        accessoryHostingView.frame.size = accessoryHostingView.fittingSize

        let titlebarAccessory = NSTitlebarAccessoryViewController()
        titlebarAccessory.view = accessoryHostingView       

        // Create the window and set the content view. 
        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")

        // Add the titlebar accessory
        window.addTitlebarAccessoryViewController(titlebarAccessory)

        window.contentView = NSHostingView(rootView: contentView)
        window.makeKeyAndOrderFront(nil)
    }
Run Code Online (Sandbox Code Playgroud)

TitlebarAccessory.swift

import SwiftUI

struct TitlebarAccessory: View {
    var body: some View {

        TextField("Placeholder", text: .constant(""))

    }
}
Run Code Online (Sandbox Code Playgroud)

结果:

macOS 工具栏中的内容

方法2(替代方法):

这里的想法是使用故事板来完成工具栏部分,而使用 SwiftUI 来完成应用程序的其余部分。这是通过创建一个以故事板作为用户界面的新应用程序来完成的。然后转到故事板并删除默认的视图控制器并添加一个新的NSHostingController. 通过设置其关系将新添加的 Hosting Controller 连接到主窗口。使用界面构建器将您的工具栏添加到窗口。

故事板配置

将自定义类附加到您的NSHostingController并将您的 SwiftUI 视图加载到其中。

示例代码如下:

import Cocoa
import SwiftUI

class HostingController: NSHostingController<SwiftUIView> {

    @objc required dynamic init?(coder: NSCoder) {
        super.init(coder: coder, rootView: SwiftUIView())       

    }

}
Run Code Online (Sandbox Code Playgroud)

使用这种方法还使您能够自定义工具栏。

  • 对于第一个解决方案,没有。但是,看看我在上面的回复中添加的替代方法。这样,您就可以选择自定义工具栏。 (2认同)