Liquid GlassのToolbarのボタンのアイコンの色がダークモードの時に黒くなっていた

著者: 奥日曜 閲覧数: 51

公開日時: 最終更新:

はじめに

初めまして、奥日曜です。

Railsでこのブログサイトを作って満足して、結局記事を投稿していなかったので今回が初投稿になります。

今回は、iOSのLiquid Glassのツールバーのボタンの色が思っていた色と少し違う色になってしまっていたので、その事象について記事にします。

何に困ったか

iPhoneのプリインストールアプリでよく見る、保存とか完了を表す下のようなボタンは、アイコンの色が真っ白ではなく、少し透過されています。

ただ、私の実装では、ボタンのスタイルが以下のように、黒くなったり微妙に標準のものと違う色にしか出来なかったりという形になってしまいました。

今回は、どういう実装をしていたから期待した色になっていなかったかを書いていきます。

ダークモード時に黒色、ライトモード時に白色になっていた実装

import SwiftUI

struct ContentView: View {

    var body: some View {
        NavigationStack {
            Text("Test")
                .navigationTitle("Liqud Glass Toolbar")

                .toolbar {
                    ToolbarItem(placement: .cancellationAction) {
                        Button("Cancel", systemImage: "xmark") {
                            // ボタンのアクション
                        }
                    }
                    ToolbarItem(placement: .confirmationAction) {
                        Button {
                            // ボタンのアクション
                        } label: {
                            Image(systemName: "checkmark")
                        }
                         .buttonStyle(.glassProminent)
                    }
                }

        }
    }
}

Button { アクション } label: { 画像} の構文で作成したボタンに対してglassProminent を適用して、プライマリボタンっぽい色合いにしようとしました。

確かに、青塗りになったり、ガラスっぽい手触りにはなったのですが、ボタンの中の色合いがダークモード時は真っ黒、ライトモード時は真っ白になってしまうので、Appleの標準の色合いとは印象が異なり違和感が出てしまいました。

微妙に違う色になっていた実装

import SwiftUI

struct ContentView: View {

    var body: some View {
        NavigationStack {
            Text("Test")
                .navigationTitle("Liqud Glass Toolbar")

                .toolbar {
                    ToolbarItem(placement: .cancellationAction) {
                        Button("Cancel", systemImage: "xmark") {
                            // ボタンのアクション
                        }
                    }
                    ToolbarItem(placement: .confirmationAction) {
                        Button {
                            // ボタンのアクション
                        } label: {
                            Image(systemName: "checkmark")
                                .foregroundStyle(.white)
                                .opacity(0.7)
                        }
                         .buttonStyle(.glassProminent)
                    }
                }

        }
    }
}

Apple標準のボタンの色に近づけるため、チェックマークの色を白色に指定して、少し透過させるアプローチを取りました。

ただ、このボタンの色も微妙に標準的なボタンの色と違うので違和感があります。

やりたかったボタンの色

import SwiftUI

struct ContentView: View {

    var body: some View {
        NavigationStack {
            Text("Test")
                .navigationTitle("Liqud Glass Toolbar")

                .toolbar {
                    ToolbarItem(placement: .cancellationAction) {
                        Button("Cancel", systemImage: "xmark") {
                            // ボタンのアクション
                        }
                    }
                    ToolbarItem(placement: .confirmationAction) {
                        Button("Done", systemImage: "checkmark") {
                            // ボタンのアクション
                        }
                    }
                }
        }
    }
}

先程までとのアプローチと異なり、今度はButton("ラベル", systemImage: "画像") { } の書き方をしました。

すると、期待したボタンの色合いになりました。

なぜ期待した色にならなかったから

どうして最初の書き方では標準的な色にならなかったか。

それは、Button { アクション } label: { 画像 } の書き方で作られるラベルはカスタムビューになるからだと思っています。

init(action:label:)

Creates a button that displays a custom label.

のようにAPIのドキュメントを見ると、私が最初に使っていた構文はカスタムビューを作る構文になっています。

反面、init(_:systemImage:action:) のドキュメントにはカスタムラベルを作るといった記載はないので、labelのスタイリングはデフォルトの挙動に委ねるものになっていると思われます。

カスタムビューになってしまうと、ラベルに自動的なスタイリング付与がされなくなってしまうため、アイコンの色が標準的なものに合わせづらくなってしまうのだと思います。

終わりに

今回は、Toolbar内のボタンが期待したスタイルにならなかった経緯について書きました。

Button { アクション } label: { 画像 } の構文がカスタム要素としてラベルを作っていることを普段意識していなかったのでこの問題にハマってしまいました。

Liquid Glassでは、OSのスタイリングに委ねたい場面が増えると思うので、この辺りを意識しながらAPIを使っていきたいと思いました。

この記事に関して、「こうした方が良いのでは?」「ここ間違ってるよ」などのご指摘がある場合は以下までお願いします。

https://x.com/Okunichiyou

0