【SwiftUI】ToolbarItemをbottomBarに複数配置した場合にアイテムを中央に配置する方法

2023.02.22

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

SwiftUIでToolbarItemを.bottomBarに複数配置した場合にアイテムを中央に配置する方法を調べたので記載しておきます。

環境

  • Xcode 14.2
  • iOS 16.1

アイテムをbottomBarに配置した挙動

アイテムが1点のみの場合は中央に配置される

ToolbarItemPlacement.bottomBarに指定した場合は、デフォルトで中央に配置されます。

struct ToolbarCenterView: View {
    var body: some View {

        NavigationStack {
            Text("I want the toolbar to be centered.")
                .toolbar {
                    ToolbarItem(placement: .bottomBar) {
                        Text("center")
                    }
                }
        }
    }
}

アイテム2点を追加すると両端に配置される

struct ToolbarCenterView: View {
    var body: some View {

        NavigationStack {
            Text("I want the toolbar to be centered.")
                .toolbar {
                    ToolbarItem(placement: .bottomBar) {
                        Text("center")
                    }

                    ToolbarItem(placement: .bottomBar) {
                        Image(systemName: "plus")
                    }
                }
        }
    }
}

bottomBarの中央にアイテムを配置する

statusを指定したアイテムは中央に配置される

ToolbarItemPlacement.statusに指定した場合は、デフォルトで中央に配置されます。

statusのドキュメントにもそのことが明記されています。

ステータス項目は本質的に情報提供を目的としており、ユーザーが実行できるアクションを表すものではありません。たとえば、新しいメッセージを確認するためにサーバーと最後に通信した時刻を示すメッセージです。

iOS および iPadOS では、システムはステータス項目を下部ツールバーの中央に配置します。

引用: Apple Developer Documentation - status

struct ToolbarCenterView: View {
    var body: some View {

        NavigationStack {
            Text("I want the toolbar to be centered.")
                .toolbar {

                    ToolbarItem(placement: .status) {
                        Text("center")
                    }

                    ToolbarItem(placement: .bottomBar) {
                        Image(systemName: "plus")
                    }
                }
        }
    }
}

  • .status以外のToolbarItem.bottomBarにある場合
    • 1点ある場合、そのアイテムは強制的に左側に配置される
    • 2点ある場合、そのアイテムは両端に配置される

Spacerを使用してアイテムを中央に配置する

SpacerのToolbarItemを使用する方法

愚直にToolbarItem(placement: .bottomBar)Spacer()を追加して配置する方法です。配置は出来ましたが、コードが冗長な気がします。

struct ToolbarCenterView: View {
    var body: some View {

        NavigationStack {
            Text("I want the toolbar to be centered.")
                .toolbar {

                    ToolbarItem(placement: .bottomBar) {
                        Spacer()
                    }

                    ToolbarItem(placement: .bottomBar) {
                        Text("center")
                    }

                    ToolbarItem(placement: .bottomBar) {
                        Spacer()
                    }

                    ToolbarItem(placement: .bottomBar) {
                        Image(systemName: "plus")
                    }
                }
        }
    }
}

ToolbarItemGroupを使用する方法

上記のSpacerのToolbarItemを使用する方法だと少し冗長になってしまいます。ToolbarItemGroupを使用することで、Toolbarに配置するアイテムをグループ化することが出来ます。

struct ToolbarCenterView: View {
    var body: some View {

        NavigationStack {
            Text("I want the toolbar to be centered.")
                .toolbar {

                    ToolbarItemGroup(placement: .bottomBar) {
                        Spacer()
                        Text("center")
                        Spacer()
                        Image(systemName: "plus")
                    }
                }
        }
    }
}

HStackを使用する必要がない

最初下記のように記述して、「あれ?描画されないな」となってしまいました。

ToolbarItemGroup(placement: .bottomBar) {

    HStack {
        Spacer()
        Text("center")
        Spacer()
        Image(systemName: "plus")
    }
}

ToolbarItemGroup内のコンポーネントは上から順に左から配置されるので特にHStackを使用する必要はありません。

まとめ

  • bottomBarに配置するアイテムが1点のみで中央の場合は.statusを使用するのが良さそう
  • ひとつのToolbarItemPlacementに複数のアイテムを配置する際はToolbarItemGroupで集約出来る
  • ToolbarItemGroup内のコンポーネントはHStack使用しなくても左から配置される

おわりに

まだまだToolbarItemPlacementは他にもあるので色々触って遊んでみたいと思います。

参考