ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
iOSのダークモードを実装する
UIKitエンジニアリングチームによる、iOSのダークモードの基盤となる原則や概念に関する説明をお聞きください。このセッションでは、動的に変化する色や画像を使用してAppをダークモードに対応させ、ユーザーに気に入ってもらえるような体験を追加するための原則について説明します。
リソース
関連ビデオ
WWDC22
WWDC19
-
ダウンロード
(音楽)
(拍手) おはようございます Implementing Dark Mode in iOSの セッションへようこそ 私カートとタイラーがご紹介します
iOS 13にダークモードを搭載するため すべてのUIを 暗い背景でも映えるようにしました iOSの見た目がすっかり変わります ダークモードを導入する方法を ご紹介します 導入は簡単です 実演しながらご紹介します ダークモードは柔軟性のある 強力なシステムです 思った通りの表現ができるでしょう まずはデザインについてです 例をお見せします ご存知のAppです ダークモードにしても レイアウトと機能は変わらず 見た目だけが違います iOSのデザインを 拡張したものと言えます 3つの要素を考慮しました まず 一番大事なのは色です これまでは ハードコーディングされており 各UIのRGB値を指定していました ダークモードでは ほぼ全ての色を変える必要があります たくさんの色を 整理する必要もありました
そこで“意味のある色”を 使用することにしました 色の名前に意味を持たせたのです このtextLabelは labelという名前で テキストとラベルの デフォルトの色です 背景は systemGroupedBackgroundです グループ化された tableViewを使用しており UITableViewによって デフォルトで表示されます このアイコンでは systemBlueを使用しています ただの青ではなく 他の色と調和するよう工夫されています このようにUIの実装には それぞれに適切な色を選びます
ライトモードに変更しても 同じ色ですが これらの色はダイナミックなので モードに合わせ 値が異なる場合があります このような色を使うと UIKitが調整をしてくれます モードを気にする必要はありません モードを変更しても 作業が発生しません 今回 新しく使える色について 例をお見せします
一緒に機能するように 一連の背景色があります systemBackgroundは 基本となる背景色でライトモードでは純白です ダークモードでは真黒です secondaryとtertiaryの 背景色もあり Appで 情報の階層構造を構成できます ダークモードは ライトモードの単純な反転ではありません 階層の概念は テキストにも使用されます 4段階の色があり 重要な項目を強調することができます 原色はタイトルなどに使用できます 二次色は サブタイトルなどに使用できます
“Human Interface Guidelines”で 詳しく説明しています 自分で色を 作成したい場合もあるでしょう ダイナミックカラーの作り方は あとで説明します
では次に マテリアルについてお話しします 写真Appでの一例です マテリアルの要素は 色だけではありません マテリアルを半透明に見せる blur effectはその1つ その上にはblurのかかっていない 際立っている部分があります どんな写真もきれいに見せることができ 明暗どちらのモードでも機能します
デザインシステムの3番目は― UIKitにビルトインのビューと コントロールです 同じ色とマテリアルが使用されています すべてが調和するデザインです
ダークモード用にデザインするなら このデザインシステムの活用方法を 学びましょう それからカスタマイズすべき部分を 決めるのです 多様な要素を すべて提供はできませんが 必要な機能は搭載されています
デザインが決まったら 実装方法を見ていきましょう
iOS 13 SDKでAppをビルドしたら ライトモードとダークモードで 表示できます ダークモードに切り替え― どう見えるか確認してください 手を加えるべき部分があるはずです 我々が自動的には調整できない部分です Appがどう見えるかを決めるのは 皆さんです 最初に行うのは 色の変更です これまで各UI色には 1つの値しか持たせられませんでした これを動的=ダイナミックにできます ライトモードとダークモードで 違う値を指定できます あるビューで背景またはテキストの色を ダイナミックに指定すると UIKitは自動的に適した値を選択し モードに合わせて更新します 色の指定が一度で済みます macOSのダークモードは NSColorで決められています まったく同じパターンです
ではAppに ダークモードを実装します タイラーが実演します
(拍手)
ありがとう カート
ここではiOS 12向けに作成された 簡単なデモAppを使います iOS 13で ダークモードをサポートするため 加えられた変更を説明します
何を変更すべきかが 分かると思います 右のシミュレータで Appを実行します ごくシンプルです ダークモードではどう見えるでしょう Xcodeで― 新しいEnvironment Overrides機能を 使います Xcodeで― Interface Styleオーバーライドを 適用します ダークモードに切り替わりました 画面下のタブバーが ダークモードに変わっています UIKit標準のタブバーを 使用しているからです でもまだ 十分暗くなっていないので 作業が必要です UIがどのようにStoryboard内で ビルドされているか見てみましょう
これがホーム画面です 白い背景が 変更されずに表示されています StoryboardでViewを選択します Attributes inspectorで 白がハードコーディングされています 今までとは違い― カートが説明した ダイナミックカラーに切り替えます これに適した色として― 一覧からSystem Background Colorを選びます 何も変わらないのは― ライトモードの背景色が白だからです Storyboardエディタ内で ダークモードに切り替え 確認しましょう こうすると― ダークモードの色で 見えるようになります
でも テキストが見えません テキストが黒だからです まずタイトルのラベルから始めましょう 右側を見てください テキストはBlack Colorと設定されています これをダイナミックカラーに切り替えます Label Colorがいいでしょう テキストが白く表示されました 今度はText Viewを選択し― ここの黒の設定も変更します
変更できたので シミュレータで確認しましょう
ライトモードで実行します Environment Overridesで ダークモードに切り替えます
見やすく変わりました さらに手を加えましょう 上にある星のマークは このAppのロゴです ダークモードで 別の色で表示させてみます 簡単です Storyboardで画像を選択します Image Viewを見てください Asset Catalogの画像が 指定されています テンプレート画像として レンダリングされる設定なので Image ViewのTintの設定色が 画像に適用されます Asset Catalogで定義した ロゴの色に設定されているので― この小さな矢印をクリックして 色の設定を見てみましょう これがカスタマイズされた緑色です ダークモードでの 見た目を変えたければ ダークモード用に 新しい設定を追加します 終わったら ダークモード用に色を変更します ここでは黄色を選びます モードによって自動的に色を変える 準備ができました 保存したらStoryboardに戻ります
プレビューでモードの明暗を 切り替えてみましょう 自動的に色が変わりますね
(拍手) 更に― 背景画像の変更もできます 南国のビーチが表示されていますが ダークモードでは きれいな夕焼けにできたらいいですよね Image Viewで 今度は画像を変更します Asset Catalogにある ヘッダー画像を見てみます 矢印をクリックします
この画像ですね 色と同様に画像を変更しましょう ダークモード用の設定を追加します そこに夕焼けの画像を― ドラッグしてください 保存したら シミュレータで見てみましょう
これはライトモードです 見た目は変わっていません ダークモードに切り替えると すべての要素が ダークモード用になりました (拍手) Asset Catalogにある ダイナミックなカラーやイメージを使用し 画像や色を自動的に変更できます コードを入力する必要はありません XcodeとUIKitを使う理由は ここにあります Appの起動時に ダークモードになるよう― App の起動Storyboardにも 同様の変更を加えることができます
他の画面も見てみましょう
Learn Moreボタンをタップすると 新しいカードスタイルに view controllerが表示されます ダークモードを適用しましょう 画面の下半分では 複数のマテリアルを利用しています 背景画像は ぼかされていて はっきりとした ラベルがその上に表示されています ここからはカートが― ダークモード用に視覚効果を 使う方法について説明します
ありがとう タイラー (拍手) ではマテリアルの例を紹介します 新しいblur effectです Thick, Regular, Thin, Ultra thinの― スタイルがあります 明暗どちらのモードでも機能します 使い方を説明します 背景のviewに blur effectを適用してみます その場合はまず UIBlurEffectを作成して スタイルを指定します .systemMaterialをお勧めします 次にこのエフェクトを使い UIVisualEffectViewを作成 サイズと位置を整え― UIVisualEffectViewを ビュー階層に配置します 下にあるものがぼやけます
blurに加え vibrancy effectも使えます 背景のマテリアルの一部が際立ちます 複数のvibrancyスタイルが 提供されています テキスト用には4つ 大きな塗りつぶし領域には3つ 細い区切り線用もあります 明暗どちらのモードにも対応 vibrancy effectを 実装してみましょう 必ずblur effectの上に追加します 前と同じ方法で― UIVibrancyEffectを作成して スタイルを指定します 大きなエリアの表示に fillを使います UIBlurEffectへの参照が必要になります 2つが連動するからです
効果の適用には もう1つVisualEffectViewを作成し UIBlurEffectに組み込みます UIVisualEffectのサブビューとして 直接追加しないでください 代わりにcontentViewを使用します ここで際立たせるビューを 追加します contentViewの配下に Vibrant Viewを追加しました このとおりです ビューの背景色は不透明ですが vibrancy effectが確認できます vibrancyスタイルでは色は無視され alphaのみが反映されます 続いてタイラーが マテリアルの追加を実演します
(拍手)
Learn Moreの画面を 見てみましょう この画面は全体が コードでビルドされています UIViewControllerの部分では loadViewメソッドで 組み立てられています ダークモードでは どう見えるのでしょう Environment Overridesで 切り替えます いくつか変わったところがあります UIKitのナビゲーションバーがその1つ そしてダイナミックカラーと画像も 設定したので 先ほど行った変更が機能していますね でもまだ背景が白く― マテリアルの見た目もよくありません 変更しましょう ビルド方法を見てみます まず 背景でこのビューを設定します 背景の設定はここです 新しいシステムの背景色に 切り替えます またsystemBackgroundを選びます
次に星の画像を設定します Asset Catalogの色を使用しているので 変更は必要ありません
次にLearn Moreラベル この画面のタイトルです 黒がハードコーディングされているので 変更します labelを選びましょう
次に 画面の最背面には 画像が設定されています ここです その上にあるのが― blurを含む視覚効果のビューす この“.light”スタイルの blur effectです 更にその上はvibrancyを含む 視覚効果ビューです ここです 最後にvibrancyViewの中に labelの設定があります これらを変更するには まずダイナミックなblur effectに切り替えます light effectはダイナミックではないので ダークモードに切り替えても 変更されません そこでiOS 13にあるsystemMaterialの パレットを使用します systemThinMaterialなら― 先程と似た表示になるでしょう 次にvibrancyのスタイルも 適用してみます 使いやすい 階層構成になっています 二次的コンテンツには styleパラメータで secondaryLabelと指定します 表示がどう変わるか見てみましょう 先程の画面を開きます ライトモードでは変わっていませんね ダークモードにすると― どうでしょう すべてが切り替わりました (拍手) 今回は 確かに コードで書きました しかし モードの確認や 切り替えのために― コードで書かなくてはならないという事ではありません ダイナミックなシステムの色とマテリアルを 活用しているからです カートにもう少し詳しく 説明してもらいましょう
ありがとう (拍手) 皆さん 気付いたでしょうか? Appの主な背景色として 黒を使用しました 新しいビューの表示でもそうしたのですが よく見ると明るめの灰色です これはダークモードに 2つのレベルがあるからです 画面の全面に広がる背景が base levelです その上のレイヤのコンテンツが elevated levelです ダークモードの背景色は elevated levelになると より明るい色となります より下の黒い背景と区別するためです 前面の色は変わりません iPhoneではご覧のように モーダルビューの表示の際に発生します iPadではマルチタスクの Split Viewで発生します 画面全体を占領しませんので
ダークモードの実装の 基礎を学びました
すべて自動的に行われるんです ダイナミックの機能を更に見てきましょう 柔軟に活用していただくためです 色がダイナミックに設定されますが モードをどう識別するのでしょう Trait Collectionを使います AppのビューやViewControllerにあり ビューの見た目を 決めるのに役立ちます 例ではすべて 同じTrait Collectionです userInterfaceIdiomは“.phone” iPadやCarPlayではありませんので ダークモードなので userInterfaceStyleは“.dark” userInterfaceLevelは 全画面表示ですので“.base”です 見た目の設定を確認するには Trait Collectionで― UIのスタイルなどを見ればいいのです
ダイナミックカラーは Trait Collectionで決まります 最終的な色は ダイナミックカラーとTrait Collectionの― 組み合わせで決まるのです 通常は自動的に行われますが 手動での決定も可能です ダイナミックカラーと Trait Collectionがあるとします 色の最終決定には “dynamicColor.resolvedColor(with:traitCollection)” と記述します ダイナミックではなくなった色になります どの色にも使えます ダイナミックではない色は そのままです カスタマイズも可能です Asset Catalogでも可能ですが コードでもできます UIColorをクロージャで初期化して 変数にTrait Collectionを使用します クロージャが別の色を返します ダイナミックカラーを最終決定する際は Trait Collectionを含む クロージャが呼び出されます そのTrait Collectionで 別の色を返せます これは先ほどの図の実装例です
ダイナミックカラーを 他の色のように直接使えるなら どう自動的に決定されるのか? ダイナミックカラーの RGBコンポーネントを求めたら 結果が返されます 黒の場合は000です Trait Collectionは使いません
currentという新しい属性を 使うのです これはUIKitで設定されています 色はcurrentTraitCollectionで 決まります Macと同じパターンです NSAppearance.currentと 同じ概念なのです 特定のメソッドを呼び出す際 currentTraitCollectionを設定します 例を示します UIViewサブクラスがあり― drawメソッドを オーバーライドしています
このメソッドを呼び出す前に UIKitはcurrentTraitCollectionを ビューのtraitCollectionに設定します ですので ダイナミックカラーを決定する場合 ビューのTrait Collectionを 使用します モードを切り替えると UIKitはdrawメソッドの オーバーライドを検知します setNeedsDisplayを呼び 再度新しい色をdrawします
他のメソッドの前にも currentTraitCollectionを設定します ビューのサブクラスやViewController PresentationController― drawを説明しました レイアウトの途中でも設定します layoutSubviewsをオーバーライドし 色を決めるコードを追加します setNeedsLayoutで 再度レイアウトが行われます ViewCotrollerと PresentationCotrollerも同様です
最後にTraitが変更されると 3つのオブジェクトが traitCollectionDidChangeを取得します ビューは tintColorDidChangeを取得します ダイナミックカラーを すぐに変更できて便利です 重要な点があります これらのメソッド以外で currentTraitCollectionは 特定の値を持つと限りません 別の方法での決定は対応が必要です その例です
CALayerやCGColorのような 低いレベルのクラスは ダイナミックカラーを理解できません 例は レイヤの作成と 境界線の色設定です CGColorを使いますが ダイナミックではありません UIKitでCGColorを呼ぶには 調整が必要です これまでのメソッドでなければ 自分で処理を管理する必要があります まずビューのTrait Collectionが 必要です その使い方は3つあります 1つ目は説明しました Trait Collectionで 色を決定する方法です 色が1つではなく 複数の場合は面倒です 毎回 処理が必要です 2つ目はより簡単で― performAsCurrentを呼ぶだけです Trait Collectionが currentTraitCollectionとなり クロージャ内のコードを 実行します これで正しい値を取得できます
3つ目の方法では― currentTraitCollectionを 直接設定します 難しそうですが安全な方法です 副次的影響もありません バックグラウンドスレッドでも使えます 実行中の特定のスレッドにのみ影響し メインスレッドには影響しません currentTraitCollectionを保存し あとで復元すれば 他のコードが関係していても安心です performAsCurrentも 同じことです
こういう処理の場合― どういった時にダイナミックカラーを 再計算するすべきでしょうか 通常はTraitの変更時です traitCollectionDidChangeが 呼び出されますがー Traitの変更は色に限定されません UIのスタイルがライトからダークに 切り替わる場合は当然ながら色に影響します しかしAppのサイズ変更で― sizeクラスを変更しても 色には影響しません hasDifferentColorAppearance メソッドで 変更を確認しましょう 変更が無い時はダイナミックカラーを 再計算すべきではありません
最後に画像についてです ダイナミックな画像は Asset Catalogで― 作成できます UIImageViewで その画像を表示する際 Trait Collectionで 表示する画像が決まります
UIImageViewの機能です UIColorとは異なり UIImageはー currentTraitCollectionを 考慮しません そのため UIImageViewをお勧めしています 自分で解決したい場合には― 画像のimage Assetから求めます 画像のバリエーション群です
特定のTrait Collectionに 一致する画像です
新しいバリエーションを 実行時にImage Assetに登録する事もできます 独自の画像の場合は 明暗両モード用を追加します Image Viewに設定するだけです ダークモードの注意点を タイラーからお話しします
(拍手) ありがとう カート まずTrait Collectionの復習です ダークモードで重要になるからです 一番重要なのは Trait Collectionが複数あることです Trait CollectionはAppの ビュー階層で 画面のルートレベルから 始まっています その下がiOS 13で加わる UIWindowScene そしてUIWindow それ以降では UIPresentationControllerや― UIViewControllersへと続きます 最終的に 各UIViewController内の UIViewまで 続きます そのため最も限定的な ViewやUIViewControllerの― Trait Collectionを使うべきです
Traitの値が変更されると 変更があった全オブジェクトの traitCollectionDidChangeを 受け取ります ダークモード設定が変わると Traitの変更が一通り行われます 更に詳しく話します iOS 13では新たな動作があるので 図の下半分に注目して 変更の例を見てみましょう
ビュー階層に 追加したいビューです これがViewController内のビューになります
まずこのビューを作成します 初期化中はまだ― ビュー階層には追加されません iOS 13ではUIKitが 作成したビューがどこに入るか 予測します 作成したビューのTrait Collectionは それを基に決められます ではこのビューを追加して… すごいでしょ? (笑い声) (拍手) ではビューを ビュー階層に追加します addSubviewを呼ぶと こうなります 親TraitからTraitを継承します この場合は上のViewControllerです しかし Trait Collectionは 正しい予測でした そのためビューを ビュー階層に移動しても Traitの変更はありません これらは iOS 13での動作です Traitは初期化中に予想されます ViewControllerとビューはすべて 最初にTrait Collectionを 受け取っています traitCollectionDidChangeは 変更があった時だけ呼ばれます iOS 13向けに既存のAppを アップデートする時は Trait Collectionの変更によって 既存の動作に変化がないか注意しましょう 以前はビュー階層への追加で Traitに変更があったからです iOS 13で行われるTraitの変更を 見ていきましょう 新たにデバッグログが追加されました このlaunch変数で有効にします traitCollectionDIdChangeが 呼び出された瞬間や― 変更の詳細が確認できて便利です
既存コードの更新や Traitを使うコードの追加には layoutがTrait Collectionを読み取り 処理を実行したあとにしましょう Traitの更新は常にlayoutの前です これらのメソッドで取得する場合は 予想ではなく確実なものとなります 親から継承された 実際の値を反映します
layoutメソッドにコードを書くと ビュー表示時に頻繁に 呼ばれます layoutが必要な時です 処理する際は 不必要に繰り返さないでください
Trait Collection使用時の 注意点でした Trait Collectionは 実はApp内で変更可能です これはその例です 他の画面はライトモードでも Learn More画面だけ 常にダークモードとする場合です Traitの階層構造を利用します
この図はAppを示します 通常はlightのUIスタイル設定です このとおりです 右下のUIViewController内を ダークモードにするには Traitをdarkで オーバーライドします UIViewController内の すべてがdarkになりました 他の部分は ライトモードのままです オーバーライドの使い方は? iOS 13の新しいAPIで 簡単に行えます UIViewControllerと UIViewのプロパティで UIUserInterfaceStyleを設定します するとその内部のすべてに 適用されます UIViewControllerのプロパティを 使うようにしてください UIViewは 変更の対象に― UIViewControllerがない時だけ 使いましょう 注意事項があるので ドキュメントを参照してください またApp全体を常に 明暗どちらかに設定するには Info.plist keyを使えば 簡単です
オーバーライドには 既存APIも使えます ViewControllerや PresentationControllerにある― どのTraitもです 設定するTrait Collectionには オーバーライドするTraitの値だけを 含んでください その他は 指定しないでおきましょう UIKitが自動的に 通常の継承値を埋めるからです iOS 13のTrait Collectionの 紹介でした
その他 今年発表のAPIの変更点や ダークモード適用時の 注意点を説明します まずはステータスバーです
これまではスタイルが2つでした .defaultと.lightContentです
iOS 13では新たに .darkContentが加わりました .defaultスタイルに取って代わり .defaultは 自動切り替えモードとしました
ステータスバーの外観を決める― UIスタイルで切り替わります ここでも ステータスバーのスタイルを 好みのものにオーバーライド可能です UIScrollViewの インジケータのスタイルも更新しました これも似た仕様です
次にActivity Indicatorについて 説明します iOS 13で 既存のスタイルは 廃止されました 特定の色を示していて 適用できないからです 代わりに 新しいスタイルを導入しました これらはActivity Indicatorのサイズにのみ 基づいています またデフォルトでダイナミックな灰色を使うので 明暗どちらのモードでも きれいに表示されます 既存の色プロパティで ダイナミックなカスタムカラーや 白などの静的な色を 指定することもできます
Appでテキストを処理する場合の 注意点があります UILabelやUITextFieldなどと テキストクラスは デフォルトではLabelの色を使います TextFieldやラベルなどのテキストが どちらのモードでも デフォルトで正しく表示されます しかしAttributed Stringを使用して Attributed Textを設定や drawする場合は foregroundColorを指定しましょう 指定せずにdrawすると このように― テキストに黒が適用されます
ダークモードで テキストが黒い場合は labelのようなダイナミックカラーに 設定を変えましょう .foregroundColorの設定がその例です 簡単ですよ
WebコンテンツをAppに 埋め込んだ場合も ダークモードが使えます color-schemeプロパティか メタタグを使用します prefers-color-schemeメディアクエリを 使い― 各モード用に 色と画像をカスタマイズできます 詳しくは今年のWWDCの動画で ご覧ください
tvOSのAppを開発している場合 ダークモードを適用済みでしょう 数年前から使えましたからね 今年からtvOS 13は iOSと同じようにデフォルトで ダークモードをサポートします ご紹介したダイナミックな色や画像などの 新しいAPIは すでに利用が可能です System Materialの一部は iOS上のみでの利用です tvOSでにダークモードを 適用している場合も これらの新しい機能や APIを採用していただけます 問題がなければ 変更する必要はありません
iPadのAppをMacにポーティングする場合は 紹介したiOSのAPIで ダークモードが実現可能です Macでは システム設定の ダークモードとなります iOSと同じくシンプルです Mac上で何か違いがあるとすれば UIKitのダイナミックカラーやマテリアルが わずかに異なることです AppKitの フレームワークで提供されるものと より一致させるためです AppKitで作ったAppに並んでも 見劣りしません
ぜひiOS 13の ダークモード機能を駆使して Appを更新してみてください
iOS 13 SDKでビルドすれば デフォルトで実装されます 実演したように いくつか作業は必要です
新しい機能の使い方は簡単で すぐにダークモードが実装できます ぜひ 紹介したダイナミックな システムの色やマテルアルを 使ってみてください 独自の色や画像も カスタマイズしてみましょう 更に UIKitに組み込んだ カスタマイズ機能や柔軟性も ダークモードの実装に フル活用してください 皆さんのAppでの実装を 見るのが楽しみです
セッションページには 詳細やサンプルコードがありますよ ご清聴ありがとうございました (拍手)
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。