Mojave で搭載された「Dark Mode」の対応について、抑えておくところのメモです。
デザインで抑えておくところ
- Dark Mode と Light Mode それぞれの配色を考える必要がある
- 複雑な配色のアセットを避けるのも一つ
- デザインアセットが増えると管理コストも増えるので、一つのアセットをプログラムでその配色に塗るようにするのもよいかも
- Human Interface Guideline で例に上がっている「アセットを別々のものにする必要がある」例
- Light Mode 時インナーシャドウで表現しているところは、Dark Mode 時インナーグローで表現するようにする
- Dark Mode でインナーシャドウが使われていると、そのアセットがダークな背景に溶けてしまう
- HIG で解説されているので、詳しくは要チェック
- Light Mode 時インナーシャドウで表現しているところは、Dark Mode 時インナーグローで表現するようにする
- 消極的解決法:アプリに「Dark Mode をサポートしない」という設定ができるので一旦はこれでしのぐ
実装で抑えておくところ
画像を Dark Mode と Light Mode で切り替える
Assets.xcassets で管理する画像について、 「Appearance」 を Any, Dark
に設定して、それぞれのスロットに画像をアサインする(Dark Appearance = Dark Mode 用、Any Appearance = いまのところ Light Mode 用)。
現在の外観モード(Dark Mode かどうか)を確認する
let appearanceName = NSApplication.shared.effectiveAppearance.name
switch appearanceName {
case .aqua:
print("Light Mode")
label.textColor = NSColor.red
case .darkAqua:
print("Dark Mode")
label.textColor = NSColor.blue
default:
assertionFailure()
}
コードで切り替える場合は外観モードを確認した上で適用していきます。
外観モードが変更されたことを検知する
NSView.viewDidChangeEffectiveAppearance()
を override します。
override func viewDidChangeEffectiveAppearance() {
print(NSApplication.shared.effectiveAppearance.name)
}
macOS の設定画面で「外観モード」を変更すると、アプリでの表示も切り替わることを確認できます。
消極的解決法:外観モードをライトのみサポートする
NSApplication.shared.appearance = NSAppearance(named: .aqua)
OS で Dark Mode に設定していても、アプリは Light Mode な感じで表示されます。
OS が Dark Mode に設定してある場合、このコードが実行されてから画面に反映されるまで一瞬 Dark Mode で表示されてしまうので、バグっているように見せてしまうかも…。
サンプル
こちらに上記を試せるサンプルコード載せておきましたー
https://github.com/feb19/DarkModeSampleApp-macOS
読んでおくと良さそうなリソース
- デザイン: Human Interface Guideline - Dark Mode
- デザイン: Dark Mode List (iOS でダークモードを独自で実装しているアプリの UI アーカイブカタログサイト)
- デザイン: Material Design - Dark theme (Material Design の配色を参考にするのもよさそう)
- 実装: Apple Developer Documentation - Supporting Dark Mode in Your Interface