はじめに
こんにちは、nukkyです。
今回はiOS13から追加されたダークモードの対応に関して書いていこうと思います。
一時しのぎ
iOS 13 SDKでは、デフォルトでダークモードに対応している状態とみなされるみたいなので、
これについては、Info.plistでUIUserInterfaceStyleキーにlightを指定することで、アプリ内では常にライトモード扱いとなり、そもそもダークモードにしないという対応も可能そうです。
ただし、公式ドキュメントに以下の記述があります。
Supporting Dark Mode is strongly encouraged. Use the UIUserInterfaceStyle key to opt out only temporarily while you work on improvements to your app’s Dark Mode support.
「ダークモードへの対応を強く推奨します。UIUserInterfaceStyleキーは作業が完了するまでの一時しのぎに限られる」というような内容になっています。
時期ははっきりわかりませんがUIUserInterfaceStyleキーの使用でリジェクトをされる未来も十分あり得るため、アプリの更新・配信を今後も行うならダークモードへの対応は必須かと思います。
実装
上記の通り、ダークモードはiOS13からの対応になるのでXcodeは11以上を用意してください。
UI Element Colors
iOS13SDKにプリセットされている、UI Element Colors(.systemBackgroundColorなど)を使うと自動で下記の対応をしてくれます。
- 色を指定するviewがmodalyかどうかで濃さを変えてくれる
- iOS13以前の端末の場合、代替の色を指定してくれる(Color Set同様)
例).systemBackgroundColor の場合、whiteなど
システムと同じ色を使うのが適当なケースではこれらを利用しましょう。
こちらのプリセットでダークモード対応に必要な機能はすでに用意してくれているのでそれを活用したほうが良い場合もあります。
https://developer.apple.com/documentation/uikit/uicolor/ui_element_colors
Color Set
かといって、アプリ独自のカラーでライトもダークも対応したい!ということはあると思います。
その際はAssets CatalogのColor Set(iOS11~)で対応しましょう。
Color Setのメリットは以下のとおりです。
- Storyboard Xib, codeで色が使える
- Light, Darkの色指定が可能
カラーのタイプはここで選択します。
UI Element Colorsで用意されている色を指定することもできます。
ここを選択すると、
このように以前にはなかったカラーアセットを選択することができます。
コードで描きたい
ビューの生成時などにダークモードかどうかを判定して静的な色をセットしても、アプリ動作中にモードが切り替わったときに追随できなくなってしまいます。
モード切り替え時に追随できるようにするには、ダイナミックカラーを利用します。 UIColor にクロージャーを渡して、クロージャーの中でモードごとの色を返すようにすることで、動的な色を作れるイニシャライザが新たに導入されました。
1 2 3 4 5 6 7 | let dynamicColor = UIColor { (traitCollection: UITraitCollection) -> UIColor in if traitCollection.userInterfaceStyle == .dark { return .black } else { return .white } } |
カスタムのカラーを定義する
アプリ独自のカラーセットを UIColor のエクステンションに定義して、実際に色を指定する箇所ではこちらを利用する方法もあります。ダークモード導入以前からこのように定義しているアプリも多いと思うのでここを修正することでダークモードに対応することもできます。
またダイナミックカラーを返すようにすることで、モード切り替え時も自動的に色が置き換わるようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 | public static var background: UIColor { return dynamicColor( light: .white dark: .black ) } public static var text: UIColor { return dynamicColor( light: UIColor(hex: 0x212121), dark: UIColor(hex: 0xF5F5F5) ) } |
画像をモードで動的に変更したい
このような場合はupdateViewConstraints()やviewWillLayoutSubviews()に現在のモードの判定を行い画像の更新を行いましょう。
ダークモードの判定は以下のメソッドで行えます。
1 2 3 4 5 6 7 8 | extension UITraitCollection { public static var isDarkMode: Bool { if #available(iOS 13, *), current.userInterfaceStyle == .dark { return true } return false } } |
さいごに
私のように、めんどくさがって対応を後回しにしてたり、まだ何をやったらいいかわからない方の助けになれれば幸いです。