[SwiftUI][macOS] macOS での SwiftUI の toolbar をカスタマイズ可能にする

SwiftUI2021

macOS 上での SwiftUI の toolbar を カスタマイズ可能にする方法を説明します

環境&対象

以下の環境で動作確認を行なっています。

  • macOS Monterey beta 12
  • Xcode 13 beta5

macOS での toolbar

いくつかの macOS のアプリは、メニューバーのカスタマイズができるようになっています。

CustomizeToolbar

View - Customize Toolbar... メニューを選択すると、以下のようなウィンドウが表示され、ドラッグ&ドロップでメニューの配置を変更することができます。

CustomizeToolbarSheet

Customize Toolbar... メニュー

Customize Toolbar... を 表示する

Scene の modifier である .commands を使用して、ToolbarCommands を指定する必要があります。


//
//  ToolbarInMacNavigationApp.swift
//
//  Created by : Tomoaki Yagishita on 2021/10/20
//  © 2021  SmallDeskSoftware
//

import SwiftUI

@main
struct ToolbarInMacNavigationApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .commands {
            ToolbarCommands()     // 👈
        }
    }
}

Customize Toolbar... を enable にする

この Customize Toolbar... メニューは、表示されるようになっただけでは、enable にはなりません。
アプリの Toolbar に登録されているメニュー項目によって、enable/disable が切り替わります。

普通に、.toolbar として、ToolbarItem を追加していっても enable になりません。

DisabledCustomizeToolbar

Customize Toolbar が enable にならないケース

例えば、以下のコードでは、ツールバーに ToolbarItem は、表示されて機能しますが、Customize Toolbar... は enable になりません。


//
//  AppRootView.swift
//
//  Created by : Tomoaki Yagishita on 2021/10/19
//  © 2021  SmallDeskSoftware
//

import SwiftUI

struct AppRootView: View {
    var body: some View {
        NavigationView {
            Text("FirstPane")
            Text("SecondPane")
        }
        .navigationTitle("Title??")
        .navigationSubtitle("sub??")
        .toolbar() {
            ToolbarItem(placement: .navigation) {
                Button(action: {print("navigation")}, label: {Label("plus", systemImage: "plus")})
            }
            ToolbarItem(placement: .navigation) {
                Button(action: {print("minus")}, label: {Label("minus", systemImage: "minus")})
            }
            ToolbarItem(placement: .navigation) {
                Button(action: {print("divide")}, label: {Label("divide", systemImage: "divide")})
            }
        }
        .toolbar() {
            ToolbarItem(placement: .status) {
                Button(action: {print("multiply")}, label: {Label("multiply", systemImage: "multiply")})
            }
        }
    }
}

CustomizableToolbarContent

Customize Toolbar... メニューを enable にするためには、ToolbarContent が CustomizableToolbarContent に準拠することが必要になります。

Apple のドキュメントは、こちら

# 探した範囲では、Customize Toolbar... メニューとの関係はドキュメントには明記されてません。動作から判断してます・・・・

CustomizableToolbarContent に準拠するために必要なことは、ToolbarItem が String を値として持つ id 指定であることです。

つまり先の例では、以下のようにすることで、Customize Toolbar... のメニューが enable になり以下のような操作が可能となります。

CustomizeToolbar


//
//  AppRootView.swift
//
//  Created by : Tomoaki Yagishita on 2021/10/19
//  © 2021  SmallDeskSoftware
//

import SwiftUI

struct AppRootView: View {
    var body: some View {
        NavigationView {
            Text("FirstPane")
            Text("SecondPane")
        }
        .navigationTitle("Title??")
        .navigationSubtitle("sub??")
        .toolbar(id: "myToolbar") {
            ToolbarItem(id: "add", placement: .navigation) {
                Button(action: {print("navigation")}, label: {Label("plus", systemImage: "plus")})
            }
            ToolbarItem(id: "minus", placement: .navigation) {
                Button(action: {print("minus")}, label: {Label("minus", systemImage: "minus")})
            }
            ToolbarItem(id: "div", placement: .navigation) {
                Button(action: {print("divide")}, label: {Label("divide", systemImage: "divide")})
            }
        }
        .toolbar(id: "status") {
            ToolbarItem(id: "multiply", placement: .status) {
                Button(action: {print("multiply")}, label: {Label("multiply", systemImage: "multiply")})
            }
        }
    }
}

.toolbar と ToolbarItem に id: <String をつかった ID 指定> を使っています。

  • アプリの すべての .toolbar が CustomizableToolbarContent に準拠していないと enable になりません
  • .toolbar 配下の すべての ToolbarItem が CustomizableToolbarContent に準拠しないと コンパイルエラー になります

Customize Toolbar... でできること できないこと

Customize Toolbar... が enable になり、カスタマイズのためのシートが表示されてもできることとできないことがあります。

  • できること:Toolbar から シート上にドラッグすることで Toolbar から 削除することができます
  • できること:削除した ToolbarItem も、シートから Toolbar 上にドラッグすることで新たに配置できます
  • できること:シート下段に用意されているデフォルト配置をドラッグすると、デフォルトの配置にリセットされます
  • できないこと:ToolbarItem で指定した placement と矛盾する位置には配置できません
  • 注意:たまに動作がおかしくなりますが、試験環境がベータ版だからかもしれません

まとめ:macOS での SwiftUI の toolbar をカスタマイズ可能にする

macOS での SwiftUI の toolbar をカスタマイズ可能にする
  • CustomizableToolbarContent に準拠させた .toolbar, ToolbarItem を使う
  • 使用されているすべての .toolbar, ToolbarItem が準拠しないと メニューは enable にならない
  • ToolabrItem の placement で指定した領域内でのみ 位置調整が可能となる

説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です