#はじめに
Flutter Advent calendar 2, 1日目の12月1日です! (monoさん、始めていただきありがとうございます!)
今日は、デザイナーさんとの仕事を効率よく進めていく上で、Material Componentsをもとに共通言語を定義して、Flutterで効率よくアプリを作っていく方法について述べていきたいと思います。
なお、筆者はFlutter/Dartが、30歳超えしてからまともに学んだ初めての言語(SDK)だったりするので、その他の言語やフレームワーク(Web系, iOS, Android)と厳密に比較することができません。簡単かどうか、は今までの他の皆様の議論を見ながら勝手に解釈しているものですのであしからず。。。
さて、この文章全体の構成は以下のようになっています。
- Flutterとコンポーネントデザイン、Material component
- Material componentの簡単な始め方と構成要素の確認
- Theme WidgetとThemeData()で色とTextstyle、ついでにコーナー、ボーダー、影を定義する
- 独自Widgetを作成してコンポーネントをつくる
- まとめ
なお、今回の内容は12月11日に行われるFlutter Interactの内容を見てからアップデートされる可能性が多分にありますのでご了承ください!(Flutter Interactに思いっきりこの名前のセッションがありましたね。。)
#Flutterとコンポーネントデザイン、Material component
デザイナーの皆さんの中では、コンポーネントデザイン(アトミックデザイン、デザインシステム)が定着しつつあるように感じています。(会社によっては公開しているところもありますね。有名なのはShopifyのPolarisとか、AirBnB, メルカリさんの例, SmartHRさんはInvisionで公開中)
このようなUIのコンポーネントを予めきちんと定義されて、それぞれのページ上では必要なコンポーネントを組み合わせるだけに留めるという方向は、UIも含めたすべてのアプリの要素をWidget, Codeで表現するFlutterととても相性がいいように感じています。
さて、みなさんはMaterial componentsをご存知ですか? GoogleがMaterial Designの要素をそれぞれComponentに落とし込んで、Web, Android, iOS、そしてFlutter向けにコードも公開しているものです。2018年にMaterial Themingが公開され、Materialの良さを世襲しながら、よりアプリのブランドを反映しやすいように高いカスタマイズ性も併せ持つようになりました。Material ComponentsはThemingを利用するためのコードサンプルみたいな形ですね。
もともとFlutterではMaterialAppをベースにしてアプリを作成しますし、FlutterのMaterial Componentsのサポートを見てもFlutterとMaterial componentsの相性がとてもよいことがわかります。
Material ThemingとComponentsは、簡単に始めやすいように豊富な情報がまとめられています。ドキュメントも(英語ですが)充実していますし、それを利用したサンプルも、テイストや用途の違ったアプリについていくつか種類が用意されています。(Shrine(コードと記事), Rally(コード, 記事))
デザインツールのSketchとFigmaのためのテンプレートが予め用意され、これを利用するだけで簡単にオリジナルのMaterial designを利用したコンポーネントが作成できます。
SketchではMaterial Theme Editorというプラグインをインストールし、そこで色やテキストなどのパラメータを入れるだけで大量のコンポーネントやサンプルが作成されます。
Figmaでは、色やテキストがきちんと適用された状態のテンプレートが公開されています。これらの変数を変更するだけで求めているような独自のコンポーネントが作成されます。
このような背景がありますので、ここからはデザイナーさんにまず、Material componentsをベースとした独自のコンポーネントを定義してもらい、それをFlutter上に落とし込む、という流れを紹介していきます。
#コンポーネント間で共有される要素
コンポーネント間で共有される要素は主に色、テキストのスタイル、それぞれの要素のコーナー、ボーダー、影かなと思います。そこでまずそれらをデザインの検討が開始される前に、デザイナーさんにきちんと定義してもらいましょう。
では、それぞれについて見ていきましょう
###色
ブランドの色を決める大切な要素ですね。企業やアプリによってカラーパレットが定義されていると思います。最近ではDark modeを利用する人も増えてきているので、Dark mode用のカラーパレットを用意している方も増えてきているのかもしれません。ちなみにMaterialでは色の組み合わせを考える上で利用できるツールが公開されています。読み難さを軽減するための色の組み合わせも含めて提案してくれるので検討してみてはいかがでしょうか。
###テキストスタイル
色と合わせてアプリの雰囲気を決める重要な要素の一つがフォントを始めとしたテキストスタイルです。最近メルカリさんが独自のフォントを作成された用に、自社のブランドを表現するTypefaceを導入する企業も増えていますね。
これらは使用する場所に合わせてヘッダー、本文など何種類かの組み合わせを予め作成しておくケースが多いかとおもいます。前章であげたデザインツールのテンプレートでもテキストスタイルが予め定義されています。
###要素のコーナー、ボーダーと影
上記の2要素と比べたら地味かもしれませんが、さりげなくアプリ全体の雰囲気に実は重要な影響を与えるのが要素のコーナー、ボーダーと影です。ボタンの形が丸いのか、四角いのか、それとも切り落としたような形をしているのか。また要素も強調したい部分がどの程度その他より浮いているように見せるのか、などからアプリの雰囲気も大きく違ってきますね。(Dribbleで上がるデザインの例ではこれらの要素でいろいろと工夫がされているケースが増えている用に感じます)
#ThemeData()で色とTextstyle、ついでにコーナー、ボーダー、影を定義する
FlutterではThemeData()をTheme Widgetにわたすことで、かなり多くの値を予め定義し、それぞれのアプリのUI要素に継承することができます。(FlutterのCookbookも参照ください。) 今回はこれに加えて、その他の要素のコーナーや影、余白のデータも加えて、アプリ内で共通の要素はすべてここにしまい込んでしまおうと考えています。
では、前章の共有される要素をどのように設定していくか見ていきましょう。
###色
ThemeData()
にはアプリ内で利用する色を定義するためのプロパティが数多く揃っています。デフォルトの値をそのまま利用してもいいケースもありますので(Dividerなど)、必要なところだけカラーパレットに合わせて適用させてしまうといいかと思います。なおデフォルトで利用される色はColorSchemeに定義されています。ThemeData()
では必要なところだけ上書きしてしまえばいいかなと思います。
なお、デバイスのダークモードの適用についてはこちらの記事やFlutterのFlutter Galleryを参考にするといいでしょう。
上記のColorScheme
ですでにlightとdarkが指定されているので、ここでもやはり必要なところだけ上書きするといいと思います。ここで定義したパラメータをMaterialAppをBuildするときにTheme
でthemeおよびdarkThemeプロパティを指定してください。
###テキストスタイル
ThemeData()
の中のTextThemeのプロパティをご覧いただき必要なところを上書きしてしまうのがいいと思います。なお、このTextThemeのテキストはMaterialが2018に更新される前の名前になっているので、現行のMaterialにあったものにする場合は2018のテキストテーマを引っ張ってきて適用してしまうか、こちらの対応表を使ってデザインツールでの名前を変えてもらうようにしましょう。
###要素のコーナー、ボーダーと影
ThemeData()
のいくつかの要素ではclipやshape、elevationといった要素をそれぞれのパーツthemeの中で上書きすることができます(ButtonThemeやCardThemeなど)。そこで角のデザインを上書きするためclip、ボーダーを定義するshape、影を設定するためのelevationをそれぞれ設定していきましょう。
なおこれらThemeData()
で指定したパラメータも、それぞれのWidgetを定義するときに簡単に上書きをすることができるので、気軽に設定してしまえばいいのかなと思います。
#独自Widgetを作成して基礎となるコンポーネントをつくる
前章ではデザインツールで指定した共有要素をThemeData()
を利用してFlutter上で再現するという作業をしました。
この章では、これらの要素を利用しながらアプリの中で使う基礎となるコンポーネントを作っていこうと思います。
個人的には、Flutterで以下のようにUIパーツをつくっています。
- ページ間で共有するWidget (common_widgets)
- (1)を加工してページ専用のWidget (ボタンとかシートとか)をつくる
- (2)を組み合わせてページをつくる
これを利用してメンテのしやすいUIを作ることができるかなと思っています。僕がとても勉強させてもらったUdemyのコースを作っているAndreaのフォルダ構成も以下のようになります。(興味持たれた方は彼のYouTubeチャンネルの動画に割引コードが貼ってありますので探してみてください)
Common_widgetsはデザイナーさんが作成するコンポーネントのうち以下のようなものについて実装していくのがいいかと考えています。
- MaterialAppのものにないオリジナルのものを作るとき
- よく使う、テキストだけが変わるだけの単純なbuttonなど
- 異なるページでも共通するロジックを元にした要素など(例えばboolの値によって見た目が変わるようなボタン。(注)ロジック自体は持たない。)
- 異なるページで利用される、複数のWidgetを組み合わせた要素(
listTile
のようなもの) - iOS/Androidで極端にUIが異なる
date_time_picker
やAlertDialog
など
Common_widgetsとしてこれらを定義することで、UIの全体の更新とその適用が簡単に終わったり、それぞれのページで異なる実装が起こってしまったりしなくていいかなと思っています。
#まとめ
FlutterはMaterialComponentの存在ありきで作られているんじゃないかと思うぐらい相性がいいです。ですので、ぜひ
- Material componentsをもとにしてデザイナさんにデザインを作ってもらい、
- デザインツール上の共有要素(パラメータとコンポーネント)と
- Flutterの中でのThemeDataや共有widgetを作成してみてください。
できればお互いのパーツの名前も共通化してしまうといいかもしれませんね。
そうすることで、新しいページや要素を作るときでも、元にしているコンポーネントがわかってすぐに対応できるんじゃないかなと思います。
ここまでお読みいただいてありがとうございました!
明日はregonnさんです!