はじめに
勉強会をご覧の皆さま
元々のテーマは「10分でわかるダークモード対応」でしたが、あちこち調べているうちにページ数が30を超えてしまい、「10分ではわからないダークモード対応」になりました🙇♂️
20分には収めます
ダークモードとは?
OSシステムレベルで設定可能な、画面表示色の設定です。
Light Modeが従来通りの白基調な画面、Dark Modeは黒基調な画面です。
何が明るく/暗くなるの?
特定の何に適用すべきという法則は無いようですが、閲覧者に見せたいコンテンツ以外のウィンドウ枠、背景などに対して適用されることが多いようです。
もちろん、メインコンテンツ(テキスト色など)も背景色に応じて調整する必要があります。
ダークモードにすると何がいいの?
- 目へのダメージを抑える
- 眩しい画面を見ることによるドライアイ、頭痛、メラトニン抑制による不眠など
- バッテリーの持ちが長くなる
- OLEDスクリーンで輝度が100%の場合、DarkはLightと比較して約60%のエネルギーを節約。輝度が50%の場合、約15%節約(YouTubeアプリで計測)
- 背景は明るいより暗いほうが、メインのコンテンツを目立たせ、作業に集中しやすくする
ダークモードにする場合のデメリットや注意点
- 直射日光の下などの明るい場所で読みづらい
- ナイトモード(ブルーライトカットの)と同じように、日没〜日の出までダークモードとする設定が用意されている
- テキスト色と背景色の逆転にOCRが追いついていない
- ダークモードで撮ったスクショをGoogle翻訳にかけても(現時点では)翻訳してくれない😭
ダークモード対応OS
- Windows 10 version 1903〜
- Mac OS Mojave(10.14)〜
- Android 10〜
- iOS 13〜
ダークモード設定方法
- Windows
- スタート -> 設定 -> 個人用設定 -> 色
- macOS
- -> システム環境設定 -> 一般 -> 外観モード
- Android
- 設定 -> ディスプレイ -> テーマ
- Zenfoneの場合は 設定 -> ディスプレイ -> システムカラースキーム
- クイック設定パネルに追加したい場合は 画面上端を下にスワイプ -> 🖋
- iOS
- 設定 -> 画面表示と明るさ -> 外観モード
- コントロールセンターに追加したい場合は 設定 -> コントロールセンター -> コントロールをカスタマイズ
iOS/Androidアプリでのダークモード対応方法(アプリエンジニア向け)
iOS
準備
- Xcode 11以上のビルド環境
- iOS 13以上の実機orシミュレーター
iOSダークモード対応は急務!!
- iOSアプリが2020年4月以降、iOS 13 SDKビルドでの審査提出が必須となる
- iOS 13 SDKビルドはデフォルトでダークモードがONになる
-
UIUserInterfaceStyle
を使えば一時しのぎ出来るが、公式は移行を強く推している- 将来効かなくなる可能性が高い
まずダークモードの見え方を確認しよう!
StoryboardやXibのInterface Builder上でLight/Darkを切り替える
デバッグ実行中にLight/Darkを切り替える
Darkにして、どうなったか。弊社案件の場合
- テキストが自動で白くなったが背景も白い。文字が読めない!
- 背景が自動で黒くなったがテキストも黒(
- 濃緑基調のグラフィックが黒い背景では見えづらい
- QRコードが真っ黒黒助
何故そうなるのか
- 場所によってiOS System Colorsを使ったり使わなかったりするため
- 大人数のプロジェクトでありがちな統一感の甘さ
- とはいえiOSのStoryboardを完璧な統一感で作った人は見たことありませんが…😅
対応作業
カラーセットを使う場合
- ハードコードしている色をAssets CatalogのColor Setに移行する
- Color SetのAppearancesにてDarkを追加する
- Dark Appearanceにフォーカスを合わせ色設定する
- 色は従来のsRGB方式以外に、iOS System Colorsも選択可能
-
darkTextColor
やsystemBackgroundColor
など - 使うとOS側が色の濃さを自動調整してくれる。便利!
- 詳しくは参考記事の実践 iOS13ダークモード対応に、わかりやすく書かれています
-
カラーセットを使わない場合
- アプリ起動中にLight/Darkを切り替えられても即反映させたいので、次のいずれかの方法で実装
- dynamicColor方式
extension UIColor {
private class func dynamicColor(light: UIColor, dark: UIColor) -> UIColor {
if #available(iOS 13, *) {
return UIColor { (traitCollection) -> UIColor in
if traitCollection.userInterfaceStyle == .dark {
return dark
} else {
return light
}
}
}
return light
}
public static var textColor: UIColor {
return dynamicColor(
light: UIColor(displayP3Red: 0, green: 9, blue: 11, alpha: 1),
dark: UIColor(displayP3Red: 255, green: 246, blue: 244, alpha: 1)
)
}
}
- dynamicProvider方式
extension UIColor {
@available(iOS 13.0, *)
convenience init(light: UIColor, dark: UIColor) {
self.init {
if $0.userInterfaceStyle == .dark {
return dark
} else {
return light
}
}
}
@available(iOS 13.0, *)
public static let textColor = UIColor(
light: UIColor(displayP3Red: 0, green: 9, blue: 11, alpha: 1),
dark: UIColor(displayP3Red: 255, green: 246, blue: 244, alpha: 1)
)
}
こちらはSDKバージョンの制限を受けますが、initとして処理を書けて、定数をimmutableにできます。
Android
準備
- Android Studio 3.3以上のビルド環境
- Android 10(Q)以上の実機orシミュレーター
まずダークモードの見え方を確認しよう!
Design View上でLight/Darkを切り替える
- Night Mode -> Nightを選択
開発者向けオプションを使う
- システム -> 詳細設定 -> 開発者向けオプション -> フォースダークのオーバーライド
- アプリの実装を変えずダークモードをシミュレートできる
Darkにして、どうなったか。弊社案件の場合
- Design View上では何も変わらなかった…
- Android版は
?android:attr/textColorPrimary
などのシステムカラーを使っていなかったから - Androidチームはデザイン指示書に厳密に従ったので、システムカラーを使わなかった
- Android版は
- でも、開発者向けオプションだといい感じのダークモードになった
- iOSで起きてた問題は一切起きなかった(細かい部分を見ると直したい色はあったが)
- Android10の強制ダークモードは割としっかりダークしてくれるの例と同じような結果だった
対応作業
-
styles.xml
やcolors.xml
を別々に用意する
- Light:
res/values/*
- Dark:
res/values-night/*
- 共通のものはLight側にまとめよう
- Darkの方には、夜間モードかフォースダークを適用する(後述)
-
2つの重ね掛けはできないらしい
-
もしくは、iOSのSystem Colorsに相当するテーマの属性やマテリアルデザイン コンポーネントを利用することもできる。厳密にカラー指定しない場合はこちらがオススメ
-
色のハードコードは厳禁らしい
夜間モード機能を使う
- アプリを新規作成すると自動で
Theme.AppCompat.Light
系のテーマが適用されているが、Dark側のスタイルにはTheme.AppCompat.DayNight
を適用する
res/values-night/themes.xml
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar" />
フォースダーク機能を使う
- 各ビューを分析して自動でダークカラーに変えてくれる機能
- 先述の開発者向けオプションを使った確認では、こちらがシミュレートされる
res/values-night/themes.xml
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:forceDarkAllowed">true</item>
</style>
- 自動で変えたくないビューには、AppTheme以外のstyleを用意して適用すればよい
Androidのダークモードサポートは色々手厚い!
- より詳しく知りたい場合、こちらを参照
WebViewの場合は?
- Web側CSSで対応するらしい(StackOverflowより)
まとめ
- ダークモードは目とバッテリーに優しく、集中できる!
- iOSは2020/04まで(03末?)にダークモードを対応するか、一時しのぎでLightに固定しなければならない
- まずは動かしてみないと修正規模がわからない
- Androidはフォースダークで対応するのが手っ取り早そう
最後に大事なこと
- ダークモード対応はエンジニアファーストで提案しよう!
- 顧客やPMは、iOS SDKの事情でダークモード対応が必要なんて知る由もない
- 工数削減のために、自動調整してくれるシステムカラーは最大限活用しよう!
- 活用すれば、20画面あっても半日で終わるから怖くない(ヤバいAppは知りません)
- デザイナーにも必要な情報を公開しよう!
- 一言「ダークモード版の素材と指示書お願いします」で受けてくれるデザイナーは奇跡の存在です(個人の所感)
やっぱり言わせてください
参考
- Use Dark Mode on your iPhone, iPad, or iPod touch
- How to use Dark Mode on your Mac
- The Benefits of Dark Mode: Why should you turn off the lights?
- ダークテーマ | Android デベロッパー | Android Developers
- Dark Mode - How to support Dark Mode for iOS 13 using Xcode
- 実践 iOS13ダークモード対応
- Android10の強制ダークモードは割としっかりダークしてくれる