[SwiftUI] ColorSet を使った Dark-mode 対応

SwiftUI2021

     

TAGS:

⌛️ 2 min.
アセットカタログを使用して ダークモード 時に適切な色を設定する方法を説明します。

環境&対象

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

  • macOS Monterery beta 2
  • Xcode 13 beta2
  • iOS 15 beta
MEMO

iOS15, macOS12 に依存した機能ではありません

ダークモード

ユーザーの設定によっては、夜間はダークモードになり、色調が変更されます。(一般に暗くなります)

SwiftUI で用意されているビューを使用していると、それらのビューは、自動的にダークモードに合わせた色に切り替わります。

自作ビュー

自作のビューで、独自に色指定していると、ダークモード時に、他のビューの挙動が合わせられず、ちぐはぐな色使いになることがあります。

自作ビューの例

通常モードでは、以下のような表示になっています。

NormalMode
NormalMode

ふとダークモードにして立ち上げてみると以下のような表示になりました。

WrongDardMode
WrongDardMode

上半分は自作ビューで、背景を Color.White としていたので、ダークモードになった際に、まわりとの整合性がなくなってしまいました。

ダークモード判定

SwiftUI での実行時に、その時点でのモードを判定することができます。


@Environment(\.colorScheme) var colorScheme

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

値としては、dark と light を取り得ます。

この変数を使用して、その時点でのモードがダークモードか判定することができます。

ダークモード判定を使用して制御する

この変数を使用して、使用する色を変更することができます。

先ほどの例では、単純に以下のようにしてしまっていたために、いつでも白が使用されていました。


Color.white

以下のように変数を使用して判定する色を変更することで、ダークモードに対応することも可能です。


if colorScheme == .light {
  Color.white
} else {
  Color.black
}

ですが、この方法はあまり推奨されない方法です。

これは、tint color として、アプリ内で独自色を使用するよりも、.tintColor を使用して設定することが推奨されることと同じ理由です。システムとしての整合性を担保できないので、アプリが個別に色管理することは推奨されていません。

UIKit, AppKit でのダークモード対応

UIKit や AppKit には、UIColor と NSColor がそれぞれ 色情報を持つクラスとして定義されていました。

例えば、NSColor には、controlBackgroundColor という色が定義されていて、この色は、ダークモード/ライトモードに合わせて システムが調整してくれています。

ですので、このような色を指定することで、アプリとしてのダークモード対応を行うことができました。

ですが、SwiftUI の Color には、このような定義を持つ動的な色が定義されていません。

MEMO

強いて言えば、accentColor が近い動きをしています。

UIColor, NSColor を使用してダークモード対応

直接的には用意されていませんが、NSColor, UIColor の持つ 動的な色を SwiftUI の Color に変換して色指定する方法があります。

こうすることで、UIKit, AppKit が持つ 色管理を SwiftUI でも使うことが可能となります。

注意

動的な色は、使用時の状況で動的に変更されるので、アプリの初期化等で、色を取得してしまうと、固定色になってしまい期待する動作になりません。
必要な場面で、都度 NSColor, UIColor から変換して使用することが必要です。

Color Set を使用して ダークモード対応

アプリケーションとしては、使用する箇所に 色の名前を指定することで、ダークモード / ライトモードに合わせて OS が色を自動で切り替えてくれる方法があります。

具体的には、 Assets の中に Color Set を定義することで、OS に対して、ライトモード/ダークモード でのそれぞれの色を指定することができます。

Asset に Color Set を追加

アセットを選択して、Color Set を追加します。この時に、使用したい色名をアセット名につけます

AddColorSet
AddColorSet

Color Set に ダークモード / ライトモードの色を設定

Asset に作成した Color Set を選択すると、”Any Appearance” と “Dark” という色が設定可能になっています。

SetAssetColor
SetAssetColor

ここでの “Any Appearance” はライトモード時に、”Dark” はダークモード時に 使用される色となります。

ここでは、”boardBackground”という名称を付けていますので、この色名で色指定を行うことで、ダークモード / ライトモード時に、それぞれの色が使用されることになります。

MEMO

iOS15 / macOS12 以降では、UIColor / NSColor で定義されている動的な色から、SwiftUI の Color を作ることもできるようになるようです。
次期 OS では、UIColor / NSColor を使用して指定することが簡単になりそうです。

シミュレータでのダークモード確認

起動したシミュレータ上でダークモードを設定することもできるのですが、Xcode から実行しているのであれば、Xcode 上で簡単に ダークモード設定で動作させることができます。

DarkModeSImulator
DarkModeSImulator

この機能を使用すると、簡単にダークモード時の動作を確認することができます。

まとめ:Color asset を使った Dark-mode 対応

Color asset を使った Dark-mode 対応
  • UIColor, NSColor では、システムから動的な色が提供されているので使用する
  • UIColor, NSColor から、SwiftUI の Color へ随時変換することで、UIKit, AppKit の仕組みを利用できる
  • Asset に Color Set を作成して、ダークモード / ライトモード 時の色を指定して、使用することができる
  • Xcode から起動することで、ダークモード / ライトモード を簡単に切り替えて確認することができる

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

コメントを残す

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