Как добавить панель инструментов в приложение macOS с помощью SwiftUI?

Я пытаюсь добавить панель инструментов внутри 9X_swiftui строки заголовка в приложение macOS с помощью 9X_macos-catalina SwiftUI, что-то похожее на то, что показано 9X_macos ниже.

9X_Как добавить панель инструментов в приложение macOS с помощью SwiftUI?_osx

Я не могу найти способ добиться этого 9X_macosx с помощью SwiftUI. В настоящее время у меня 9X_osx есть панель инструментов (с текстовым полем) внутри 9X_macosx моего представления, но я хочу переместить 9X_macosx ее в строку заголовка.

Мой текущий код:

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

Итак, в 9X_macos-catalina моем случае мне нужно, чтобы текстовое поле 9X_macos-catalina было внутри панели инструментов.

24
0
5
Общее количество ответов: 5

Ответ #1

Ответ на вопрос: Как добавить панель инструментов в приложение macOS с помощью SwiftUI?

Начиная с macOS 11, вы, вероятно, захотите 9X_swiftui использовать новый API, описанный в WWDC Session 10104, в 9X_macos-catalina качестве нового стандарта. Явные примеры 9X_macos-catalina кода были предоставлены в WWDC Session 10041 на отметке 12 9X_swiftui-bug минут.

NSWindowToolbarStyle.unified

или

NSWindowToolbarStyle.unifiedCompact

А в SwiftUI вы можете использовать 9X_macosx новый конструктор .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() {}
}

25
1

  • Очень удобные ссылки! Спасибо<p><span clas ...

Ответ #2

Ответ на вопрос: Как добавить панель инструментов в приложение macOS с помощью SwiftUI?

Подход 1:

Это делается путем добавления элемента 9X_macos заголовка. Мне удалось это сделать, изменив 9X_osx файл AppDelegate.swift. Мне пришлось применить 9X_macos-catalina какие-то странные отступы, чтобы все выглядело 9X_mac правильно.

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)
    }

TitlebarAccessory.swift

import SwiftUI

struct TitlebarAccessory: View {
    var body: some View {

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

    }
}

Результат:

9X_Как добавить панель инструментов в приложение macOS с помощью SwiftUI?_macosx

Подход 2 (альтернативный метод):

Идея состоит в том, чтобы сделать 9X_macos-catalina часть панели инструментов с помощью раскадровки, а 9X_swiftui-bug остальную часть приложения - с помощью SwiftUI. Это 9X_macos делается путем создания нового приложения 9X_swiftui-bug с раскадровкой в ​​качестве пользовательского 9X_mac интерфейса. Затем перейдите в раскадровку 9X_macos-catalina и удалите контроллер представления по умолчанию 9X_swiftui и добавьте новый NSHostingController. Подключите только что 9X_mac добавленный Hosting Controller к главному 9X_swiftui-bug окну, установив его взаимосвязь. Добавьте 9X_swiftui-bug панель инструментов в окно с помощью конструктора 9X_macos-catalina интерфейсов.

9X_Как добавить панель инструментов в приложение macOS с помощью SwiftUI?_osx

Прикрепите настраиваемый класс 9X_swiftui-bug к своему NSHostingController и загрузите в него представление 9X_osx SwiftUI.

Пример кода ниже:

import Cocoa
import SwiftUI

class HostingController: NSHostingController {

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

    }

}

Использование этого подхода также 9X_macos дает вам возможность настраивать панель 9X_osx инструментов.

7
1

  • С первым решением нет. Но посмотрите на альтернативный подход, котор ...

Ответ #3

Ответ на вопрос: Как добавить панель инструментов в приложение macOS с помощью SwiftUI?

https://developer.apple.com/documentation/uikit/uititlebar

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

        guard let windowScene = (scene as? UIWindowScene) else { return }
        let window = UIWindow(windowScene: windowScene)

        if let titlebar = windowScene.titlebar {

            //toolbar
            let identifier = NSToolbar.Identifier(toolbarIdentifier)
            let toolbar = NSToolbar(identifier: identifier)
            toolbar.allowsUserCustomization = true
            toolbar.centeredItemIdentifier = NSToolbarItem.Identifier(rawValue: centerToolbarIdentifier)
            titlebar.toolbar = toolbar
            titlebar.toolbar?.delegate = self

            titlebar.titleVisibility = .hidden
            titlebar.autoHidesToolbarInFullScreen = true
        }

        window.makeKeyAndVisible()

    }
#if targetEnvironment(macCatalyst)
let toolbarIdentifier = "com.example.apple-samplecode.toolbar"
let centerToolbarIdentifier = "com.example.apple-samplecode.centerToolbar"
let addToolbarIdentifier = "com.example.apple-samplecode.add"

extension SceneDelegate: NSToolbarDelegate {

    func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
        if itemIdentifier == NSToolbarItem.Identifier(rawValue: toolbarIdentifier) {
            let group = NSToolbarItemGroup(itemIdentifier: NSToolbarItem.Identifier(rawValue: toolbarIdentifier), titles: ["Solver", "Resistance", "Settings"], selectionMode: .selectOne, labels: ["section1", "section2", "section3"], target: self, action: #selector(toolbarGroupSelectionChanged))

            group.setSelected(true, at: 0)

            return group
        }

        if itemIdentifier == NSToolbarItem.Identifier(rawValue: centerToolbarIdentifier) {
            let group = NSToolbarItemGroup(itemIdentifier: NSToolbarItem.Identifier(rawValue: centerToolbarIdentifier), titles: ["Solver1", "Resistance1", "Settings1"], selectionMode: .selectOne, labels: ["section1", "section2", "section3"], target: self, action: #selector(toolbarGroupSelectionChanged))

            group.setSelected(true, at: 0)

            return group
        }

        if itemIdentifier == NSToolbarItem.Identifier(rawValue: addToolbarIdentifier) {
            let barButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.add, target: self, action: #selector(self.add(sender:)))
            let button = NSToolbarItem(itemIdentifier: itemIdentifier, barButtonItem: barButtonItem)
            return button
        }

        return nil
    }

    @objc func toolbarGroupSelectionChanged(sender: NSToolbarItemGroup) {
        print("selection changed to index: \(sender.selectedIndex)")
    }

    @objc func add(sender: UIBarButtonItem) {
        print("add clicked")
    }

    func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
        [NSToolbarItem.Identifier(rawValue: toolbarIdentifier), NSToolbarItem.Identifier(rawValue: centerToolbarIdentifier), NSToolbarItem.Identifier.flexibleSpace,
            NSToolbarItem.Identifier(rawValue: addToolbarIdentifier),
            NSToolbarItem.Identifier(rawValue: addToolbarIdentifier)]
    }

    func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
        self.toolbarDefaultItemIdentifiers(toolbar)
    }
    
}
#endif

9X_macos

1
0

Ответ #4

Ответ на вопрос: Как добавить панель инструментов в приложение macOS с помощью SwiftUI?

Вдохновленный вашим первым подходом, мне 9X_macos тоже удалось получить панель инструментов. Поскольку 9X_macos-catalina я использую в нем Divider(), ваши Paddings 9X_swiftui-bug мне не подходят.

9X_Как добавить панель инструментов в приложение macOS с помощью SwiftUI?_macosx

Этот, кажется, работает 9X_macos-catalina немного плавнее с разными размерами макета:

 let titlebarAccessoryView = TitlebarAccessory().padding([.leading, .trailing], 10).edgesIgnoringSafeArea(.top)

    let accessoryHostingView = NSHostingView(rootView:titlebarAccessoryView)
    accessoryHostingView.frame.size.height = accessoryHostingView.fittingSize.height+16
    accessoryHostingView.frame.size.width = accessoryHostingView.fittingSize.width

9X_Как добавить панель инструментов в приложение macOS с помощью SwiftUI?_mac

Может 9X_swiftui-bug быть, есть еще более плавный способ избавиться 9X_macos от этого +16 и отступов в конце и впереди 9X_macos (есть несколько других вариантов вместо 9X_swiftui-bug FitSize), но я не смог найти ни одного, который 9X_macos-catalina отлично выглядел бы без добавления числовых 9X_macosx значений.

1
0

Ответ #5

Ответ на вопрос: Как добавить панель инструментов в приложение macOS с помощью SwiftUI?

Мне, наконец, удалось сделать это без каких-либо 9X_macosx неудобных дополнений и таким образом, который 9X_macos отлично смотрится в полноэкранном режиме. Кроме 9X_mac того, предыдущие решения не позволяют изменять 9X_macosx размер по горизонтали.

9X_Как добавить панель инструментов в приложение macOS с помощью SwiftUI?_macos

Оберните представление 9X_osx заголовка в HStack() и добавьте невидимое 9X_swiftui текстовое представление, которое может расширяться 9X_macos-catalina до бесконечности. Кажется, это то, что держит 9X_mac все в центре внимания. Не обращайте внимания 9X_osx на безопасную область вверху, чтобы теперь 9X_swiftui-bug центрировать ее по всей высоте заголовка.

       struct TitleView : View {
   
            var body: some View {
                HStack {
                    Text("").font(.system(size: 0, weight: .light, design: .default)).frame(maxHeight: .infinity)
                    Text("This is my Title")
                }.edgesIgnoringSafeArea(.top)
            }
        }

В 9X_macos делегате приложения, когда вы добавляете 9X_mac NSTitlebarAccessoryViewController(), установите 9X_swiftui-bug атрибут layoutAttribute на вершину. Это 9X_swiftui-bug позволит изменять его размер по горизонтали 9X_mac по мере изменения размера вашего окна (ведущие 9X_macosx и левые фиксируют ширину до минимума, что 9X_osx вызвало у меня много боли в поисках ответа 9X_swiftui на этот вопрос.

    let titlebarAccessoryView = TitleView()

    let accessoryHostingView = NSHostingView(rootView: titlebarAccessoryView)
    accessoryHostingView.frame.size = accessoryHostingView.fittingSize
    
    let titlebarAccessory = NSTitlebarAccessoryViewController()
    titlebarAccessory.view = accessoryHostingView
    titlebarAccessory.layoutAttribute = .top

В моем случае мне также нужны 9X_swiftui-bug несколько кнопок справа, которые располагаются 9X_mac независимо от остальной части заголовка, поэтому 9X_mac я решил добавить их отдельно, используя 9X_macos возможность добавления нескольких контроллеров 9X_macos-catalina представления

    let titlebarAccessoryRight = NSTitlebarAccessoryViewController()
    titlebarAccessoryRight.view = accessoryHostingRightView
    titlebarAccessoryRight.layoutAttribute = .trailing
    
    window.toolbar = NSToolbar()
    window.toolbar?.displayMode = .iconOnly
    window.addTitlebarAccessoryViewController(titlebarAccessory)
    window.addTitlebarAccessoryViewController(titlebarAccessoryRight)

1
0