Slide 1

Slide 1 text

iOS・Androidで使える デザインシステムをどう実装するか pixiv Inc. ああうえ 2021.9.17 19:50〜 iOSDC Track C

Slide 2

Slide 2 text

2 自己紹介 ● ああうえ / @_kwzr_ ● 仕事: pixiv Sketchの開発 ● 個人: Pose Arch 15万DL🎉 ああうえ モバイルアプリエンジニア

Slide 3

Slide 3 text

4 アジェンダ 1. デザインシステムとは 2. Kotlin Multiplatform Projectを使ったデザイントークンの実装 3. 画像・色アセットの作成 4. UIKit・SwiftUIでのコンポーネント作成

Slide 4

Slide 4 text

5 デザインシステムとは? 以下をまとめたもの ● スタイルガイド ● UIライブラリ ● スタイルガイドとUIライブラリを繋ぐ、ルール・ツール群

Slide 5

Slide 5 text

6 スタイルガイド ● デザインに関する原則がまとまったドキュメント ● ボタンの見た目など、画面ごとに違ってユーザーを混乱させない ● 統一したUIを提供することで、ブランディングを向上させる

Slide 6

Slide 6 text

7 UIライブラリ ● UIの実装をまとめたもの ● コード量・メンテナンスコストを減らし、生産性を上げる。誰が実装 しても同じものを作れるようにするのが目的 ● 以下の要素で構成される ○ デザイントークン ■ Spacing, Typography, Border Radius, Color Palette, Icon, Animation… ○ コンポーネント ■ ボタン、スイッチ、...

Slide 7

Slide 7 text

8 ルール・ツール群 ● どこにリソースを置くか?どう更新するか?などの運用ルール ● 画像の書き出し、各OSで使えるように変換するスクリプトなど ● ルールを自動化するためのCI

Slide 8

Slide 8 text

9 弊社の状況 6サービス、12のアプリ

Slide 9

Slide 9 text

10 弊社の状況 6サービス、12のアプリ Unity製 考慮 しない

Slide 10

Slide 10 text

11 状況 ● 4サービス、8アプリがデザインシステムに対応する可能性 ○ 歴史が長いアプリが多いのでまだまだ先は長い ● 各アプリの実装状況 ○ iOS ■ Interface Builderで独自のCustom Classを設定 ■ View Controllerで逐一スタイルを設定 ■ SwiftUI ○ Android ■ 独自のViewを定義 ■ styles.xmlに定義されたスタイルを適用

Slide 11

Slide 11 text

12 Webフロントでの導入 ● 2019年ごろからデザインシステムの整備・導入が進められている ● Tailwind CSSの思想で作られたユーティリティファーストなデザイン システム ○ https://inside.pixiv.blog/2021/07/01/151500

Slide 12

Slide 12 text

13 Webフロントでの導入 ● 以下のようなレイヤーで構成 ● Constants(デザイントークン) ○ Spacing, Typography, Border Radius, Palette, Icons... ● Utilities ○ Tailwind CSSを拡張したCSS層 ○ これによって、ReactでもVueでも使用可能 ● Components ○ Buttonなどのコンポーネント .bg-background1 .typography-12 const background1 = “#fff” const typography12 = { fontSize: 12, lineHeight: 20 } Components Utilities Constants

Slide 13

Slide 13 text

14 アプリにも導入する ● Webフロントで導入が進められているデザインシステムを iOS・Androidにもどのように導入するか? ● 異なるプラットフォーム間で、どうやってスタイルの一貫性を保って 運用していくか?

Slide 14

Slide 14 text

15 Single Source of Truth ● 信頼できる唯一の情報源 ○ どれが最新か、信頼性のあるデータなのか考えずに使えるよう にする ● 参照する情報が複数あると、どれを変更したり参照したりすればいい かわからない。参照元を一つにする ● マルチプラットフォーム、複数サービスへの適用を考えて、一つの情 報源を参照できるように、運用ルール、CIなどを設定する

Slide 15

Slide 15 text

16 デザインシステムの構成 library-ios library-android ● デザイントークン ● コンポーネント ● アセット ● 各プラットフォーム向けツール など image: Flaticon.com

Slide 16

Slide 16 text

17 デザインシステムの構成 library-ios library-android library-mobile-foundation ● デザイントークン ● モバイル共通の定義 ● コンポーネント ● アセット ● 各プラットフォーム向けツール image: Flaticon.com

Slide 17

Slide 17 text

18 デザイントークンとは ● Single Source of Truthを実現するためにSalesforceが提唱 ● デザインに関する以下のような定数を指す ○ Spacing ○ Border Radius ○ Typography ○ Color Palette ○ … ● 上記のような定数をYAML・JSONなどで定義しておき、 Web・iOS・Android各プラットフォームのコードに変換する

Slide 18

Slide 18 text

19 デザイントークンの実装 ● Web・iOS・Androidで最初から共通化するのであれば、以下のようなデザイ ントークン実装を採用するのも良い ● https://github.com/salesforce-ux/theo ● https://github.com/amzn/style-dictionary ● https://github.com/diez/diez

Slide 19

Slide 19 text

20 MPPを使ったデザイントークン実装 ● ピクシブで現在進めているデザイントークン実装 ● Kotlin Multiplatform Project(MPP)をデザイントークン実装に使う ● MPPとは? ○ KotlinはMultiplatform Programmingを主要な利点として上げ ている ○ Kotlinで書かれたコードをKotlin/JVM, Kotlin/Native, Kotlin/JSのネイティブコードに変換。マルチプラットフォーム での開発を可能にする ○ 2021年9月1日現在はAlpha段階 ○ Alpha段階: use at your own risk, expect migration issues

Slide 20

Slide 20 text

21 MPPの簡単な使用例 ● プロジェクトを作ると、androidMain, commonMain, iosMainのよう に各プラットフォーム用のパッケージが生成される ● 共通のコードはcommonMain / commonTestに置かれる

Slide 21

Slide 21 text

22 各プラットフォームのコードを書く ● expect, actual宣言で各プラットフォーム向けのコードを書ける

Slide 22

Slide 22 text

23 MPPを使うメリット ● Kotlinによって、より高い表現力で実装できる ○ 例えば、定義の再利用 ● YAMLやJSONなどを各プラットフォームで読まなくて良い

Slide 23

Slide 23 text

24 ピクシブでの実装 ● ピクシブでは既存の実装を生かすため、WebのTypeScript実装を JSON Schema化してKotlinの型に変換したものを配置している ● なので、前述したメリットは実はほとんどない...が ○ MPPを最初から選択できる場合は大きなメリットとなりそう ○ アプリでのみ存在する定義を吸収する層にはなっている

Slide 24

Slide 24 text

25 ライブラリとして配布 library-ios library-android library-mobile-foundation ● デザイントークン ● モバイル共通の定義 ● コンポーネント ● アセット ● 各プラットフォーム向けツール image: Flaticon.com

Slide 25

Slide 25 text

26 ライブラリとして配布 library-ios library-android library-mobile-foundation ● デザイントークン ● モバイル共通の定義 ● コンポーネント ● アセット ● 各プラットフォーム向けツール image: Flaticon.com

Slide 26

Slide 26 text

27 Multiplatform Libraryを作る ● MPPで作ったものは各OSのライブラリとして配布可能 ● IntelliJ IDEAにはMultiplatform Libraryのテンプレートがあるので これを使うのがおすすめ

Slide 27

Slide 27 text

28 Swift Packageで配布する ● multiplatform-swiftpackage Gradleプラグインを使用する ● outputDirectoryをリポジトリのrootDirに設定しておくと、GitHub 経由などでSwift Packageを取得できる build.gradle.kts 生成されるファイル

Slide 28

Slide 28 text

29 Mavenで配布 ● maven-publish Gradleプラグインを使用してライブラリを配布する ● iOSのartifactsも生成されるが、取得する際は必要なのものだけが取 得されるので、気にしなくて良いのがGood build.gradle

Slide 29

Slide 29 text

library-ios library-android library-mobile-foundation ● デザイントークン ● モバイル共通の定義 ● コンポーネント ● アセット ● 各プラットフォーム向けツール 30 アセット image: Flaticon.com

Slide 30

Slide 30 text

31 アセットの配布 ● MPPではAssetを扱えない🥺 ● iOSは画像や色をInterface Builder上から使えるようにしたり、ダー クモード対応のために、Asset Catalog対応したい ○ library-iosの層でAsset Catalogを作る ○ 既存のデザイントークンライブラリでも完全に対応されている ものがなさそう ● Androidも同様に、library-androidの層でcolors.xmlや VectorDrawableを配置してあげる

Slide 31

Slide 31 text

32 アセットの変換 ● iOS ○ Asset Catalogへの変換を地道にやる ○ iOS 12以下への対応 ■ SVG形式の利用はiOS 13+ ■ PDF形式で吐き出す必要がある ● Android ○ SVG→VectorDrawableに変換する ○ Android Studioのソースコードを参照

Slide 32

Slide 32 text

33 アイコンの自動更新 ● Figmaのアイコンが更新されたらコード側にも反映されてほしい ● Figma APIを叩いてCIでアイコンを自動更新する ○ 特定のページにある特定の命名規則のアイコンを取り出し、PR を作成する ○ 1日ごとなど定期実行する ○ https://inside.pixiv.blog/2021/01/22/170000

Slide 33

Slide 33 text

library-ios library-android library-mobile-foundation ● デザイントークン ● モバイル共通の定義 ● コンポーネント ● アセット ● 各プラットフォーム向けツール 34 コンポーネント image: Flaticon.com

Slide 34

Slide 34 text

35 コンポーネントの実装 ● library-ios, library-androidにそれぞれ実装 ● 各OS、パラダイムごとに実装を用意 ○ UIKit・SwiftUI・Android View・Jetpack Compose ○ 性質上仕方ない。将来的にはアプリ側の実装を揃えていく ● FlutterのAdd-to-appは? ○ 共通のコンポーネントを実装して、iOS・Androidから使用可 ○ 各プラットフォームでの体験を大切にするため使わない ■ MPPの思想でもUIは各OSのネイティブで実装することを勧 めている ■ https://kotlinlang.org/docs/mobile/architect-kmm-ap p.html

Slide 35

Slide 35 text

36 コンポーネントの実装(UIKit) ● デザインシステム自体の実装は、SwiftUIの方が楽... ● デザインシステムを導入するためSwiftUIを必須化するのは非現実的 ○ 引き続き、UIKitでも開発できるようにする ● Interface Builder上でスタイルが設定できるようにする

Slide 36

Slide 36 text

37 コンポーネントの実装(UIKit) ● @IBInspectableにenumが使えない問題 ○ ボタンのスタイルを設定するときにどうするか ● 2つの方法 ○ 1スタイル=1Custom Classで実装する←こちらを採用 ■ Figmaの定義と同じクラス名にする(prefixは除く) ○ #if TARGET_INTERFACE_BUILDERを使って、コード上からは enum、Interface BuilderからはIntやStringで設定する方法 ■ Int: 欠番などの扱い、Figma上のものと揃えるのが難しい ■ String: 入力補完ができない ■ IBLinterなどでLintが難しい ● UIButton.Configuration(iOS 15+)は考えない ○ iOS 14はまだしばらく切れないので...

Slide 37

Slide 37 text

38 コンポーネントの実装(SwiftUI) ● スタイルを変えるのに、独自にViewを継承して実装はしない

Slide 38

Slide 38 text

39 コンポーネントの実装(SwiftUI) ● Modifierを実装し、extensionでスタイルを利用できるように ○ デザインシステムの定義ということがわかる ○ 補完が効いて便利

Slide 39

Slide 39 text

40 コンポーネントの実装(SwiftUI) ● TypographyやBorder Radiusなどもextension化 ○ デザインシステムの定義ということがわかる ○ 補完が効いて便利 ○ .foregroundColor(PixivColor.background01) みたいな誤用防ぐ

Slide 40

Slide 40 text

42 コンポーネントの実装(Android) ● Androidも、現状の実装と将来的にどうしたいかを考えて実装 ● Android View ○ viewInflaterClassを使った、既存のXMLの置き換え ○ TextView→MaterialTextViewのように自動的に置き換えること ができる ● Jetpack Compose ○ まだ検討中 ○ SwiftUIと似たような実装になりそう

Slide 41

Slide 41 text

43 まとめ ● デザインシステムがあることによって、サービス・アプリのブラン ディングや開発体験に大きく影響 ● Single Source of Truthを実現するために、デザイントークンの実装 が重要 ○ style-dictionary、diezなど既存の実装を使うか、MPPを使うか プロダクトによって見極める ● 色や画像リソースの変換は現状ではがんばるしかない ● UIKit・SwiftUIでのコンポーネント設計方針を話した

Slide 42

Slide 42 text

45 参考文献 ● Design Systems ―デジタルプロダクトのためのデザインシステム実 践ガイド Alla Kholmatova(著), 佐藤伸哉(翻訳) ● Kotlin Multiplatform | Kotlin