マテリアルデザインってなんだろう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/924658/e0e1a571-18ac-aa97-ffcd-1b9f3935d690.png)
※画像引用：[Material Design Principles](https://material.io/design/introduction#principles)

マテリアルデザインってなんでしょうか。

ReactやFlutterを触っていると、公式が用意してくれるパーツの完成度が高くて、組み合わせるだけでそれらしいものができてしまいます。それでなんとなくマテリアルデザインをできているような気でいたのですが、他の人から説明を求められたり、デザイン案をアリかナシか考えるとき、自分の中に全く尺度がないことに気づきました

ということで一度しっかりマテリアルデザインガイドラインを読んで、まとめてみることにしました

ちなみに私の場合、「リッチデザインとフラットデザインのいいとこどりをしたもの」というひどい理解をしておりました。残念ですねー

公式はこちら
[Material Guidelines](https://material.io/design/guidelines-overview)

# マテリアルデザインとはなんだ
>Material is a design system created by Google to help teams build high-quality digital experiences for Android, iOS, Flutter, and the web.

Google発のデザイン体系を指しています。初出は2014年です

# マテリアルデザインの原則
### Material is the metaphor
>Material Design is inspired by the physical world and its textures, including how they reflect light and cast shadows. Material surfaces reimagine the mediums of paper and ink.

マテリアルデザインは（光の反射や影の差し方を含む）物理的な世界と質感を基にしています。そしてマテリアルの表面は、印刷物を思い起こさせる、とのこと

### Bold, graphic, intentional
マテリアルデザインは、印刷物のデザイン手法に基づいて、ユーザを体験に没頭させるような、階層化、意味づけ、注意づけをする

### Motion provides meaning
モーションによってユーザの注意を集め、さりげないフィードバックと一貫した遷移によって、連続性を表現する

# 物質的な世界とはなんだ
この時点では、わかるような、わからないような...なので、具体的な実装についても学んでいきます

## Environment
>In the physical world, objects can be stacked or attached to one another, but cannot pass through each other. They cast shadows and reflect light.

物質的な世界では、物体は積み重ねたり、他の何かとくっつけることができます。しかし、お互いに通り抜けるようなことはできません。そして物体は影を作り、光を反射します。マテリアルデザインには（実世界と同じように）、積み重ねるための「高さ（奥行き）」があります

### やっていいこと
![スクリーンショット 2021-06-29 22.33.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/924658/2a74c99c-113d-cc8f-074e-127df33374bf.png) ![スクリーンショット 2021-06-29 22.39.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/924658/7f878988-82f2-a5fd-c12a-a46379050fa3.png) ![スクリーンショット 2021-06-29 22.45.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/924658/0b32a751-d15f-ef72-1326-ad546f546b15.png)


左：影で高低差を表現（Flutterのデフォルト）
中：影がなく、明度差で高低差を表現
右：ダイアログとスクリム（Flutterのデフォルト）

* 高さを作る
    * 必ずしも影を作る必要はなく、色のコントラストや透明度で表現してもよい
    * ただし、製品全体で一貫性を取ること
* 移動はもちろん、縦や横に伸び縮みして変形してもいいし、回転してもいい
* マテリアルの表面は、透明、不透明、半透明にすることができる
    * ただし可読性を損なわないように
* ダイアログなど手前に表示されるコンポーネントを出すときは、背景にスクリムを作る
    * スクリム：背景を暗くしたり、ぼかしたりすること

### やらないほうがいいこと
* マテリアルの高さ（厚み）をバラバラにしない
* elevationを使わずに高さを表現しない
* ボタンを触った時などのアニメーションは、ボタンそのものをはみ出さない
* 複数の要素が同じ高さで重なり合わない
* ある要素が他の要素をアニメーションで貫通したりしない
* ガスや液体のように現れたり消えたりするアニメーションをしない
* 立体的に折れ曲がったり、畳まれるアニメーションをしない

やらないほうがいいことには、「物質世界ではありえないからやらないほうがいい」というものと、「単純化、一貫性のためにやらないほうが良いこと」の両面がありそうです。たしかに不必要な部分でユーザの注意を引きたくはないですね

これはマテリアルデザインなのか？と判断に困ったら、まずは**「実世界でありえるか？」を尺度にする**と良さそうかなと思います

#### より高さを表現するためのあれこれ
より情報の階層化をユーザに意識させるために、アニメーションを使うこともあります

* 要素をタップして全面に表示するときに、他要素が暗くなりながら表示する
* タップした要素以外を小さくスケールアウトしながら遷移する
* 要素の移動速度をズラして奥行きを表現する
* 同じ階層の要素を押しのけるように広がって全面に表示する

この辺りはやや上級テクニック感がありますね

## レイアウト
### レイアウトの原則
* 予測可能であること
    * 一貫性のあるUIと空間構成の、直感的なレイアウトを使用する
* 一貫性があること
    * グリッド、キーライン、そしてパディングを一貫して使うこと
* レスポンシブ
    * ユーザ、デバイス、画面からの入力に反応すること

### デバイスごとの推奨ブレークポイント
スマートフォンやタブレット、PCブラウザの画面サイズによってレイアウトを切り替えるアプリもあるかと思います。その場合、どの画面サイズを閾値に切り替えるのか悩むところですが、推奨サイズを用意してくれていました

[レスポンシブ列グリッド](https://material.io/design/layout/understanding-layout.html#layout-anatomy)

ちなみに、ナビゲーションドロワーは拡張時256dp、折り畳み時は72dpだそうです。出来合いのコンポーネントを使う分には意識することはないと思いますが、意外と細かく決まっているものですね

### 視覚的なグループ化をすること
* 暗黙的なグループ化
    * 関連する要素同士を互いに近づける。逆に、関連していない要素同士の間にスペースを作る
* 明示的なグループ化
    * 要素にアウトラインや高さを追加することで、明示的にグループ化をする

これは印刷物デザインにおける、似たような情報を近づけて揃え、異なる情報を離す、という話のようです。個人的には、仕切り線ばかりだと狭苦しくなる気がするので、余白を使いこなせるようになりたいと思っています

### ほとんどのサイズや位置は8dpまたは4dpに揃えられる
>To ensure that Material Design layouts are visually balanced, most measurements align to 8dp, which corresponds to both spacing and the overall layout.

視覚的な一貫性を保つために、マージンや全体的なレイアウト、コンポーネントのサイズは8dp刻みに調整されます。アイコンやフォントはもう少し細かく、4dpに揃えられます。

これは知りませんでしたね...今まで微調整していたのはなんだったんだろう

### spとdpの違い
dp（ディップ）は、端末のピクセル密度に依存しないサイズです。一方で、 **sp（スケーラブルピクセル）はdpと同じようにピクセル密度に依存しませんが、ユーザのテキスト設定に合わせて大小します**

Androidだとテキストサイズにはspを使うよう推奨されていますが、テキストサイズを大きく変えるとレイアウトが崩れることがあります。個人的には読み物主体のアプリでない限り、多少はdpで固定してしまっても良いような気がしています

### 密度
コンポーネントには密度(density)を設定することができます。密度を上げると余白や間隔が狭くなり、一覧性がよくなります

しかし、密度を適用しないほうがいい場合があります

* ドロップダウンメニューや、ピッカー
    * ユーザに集中して何かをさせたい場合。タップ可能な領域が狭くなって使いにくくなる恐れあり
* アラートやメッセージダイアログ
    * ユーザの注意を引く効果が損なわれる

## ナビゲーション
ナビゲーションは大きく分けて3つに大別される
他と遷移の仕方が違うアプリは、自分がどこにいるのか分かりにくくなります。ここで変に個性を出さず、王道にしたがっておきたい

#### 並列要素のナビゲーション
同じ階層レベルの要素同士で移動すること。アプリで最も大元のナビゲーションである

* ナビゲーションドロワー
    * トップレベルナビゲーション。遷移先がたくさん（5個〜）ある場合
* ボトムナビゲーションバー
    * トップレベルナビゲーション。遷移先は３~5個ある場合、かつモバイルで多く使用される
* タブ
    * 任意のレベルで使うナビゲーション。遷移先は2個〜と幅広く使える

![スクリーンショット 2021-06-29 22.52.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/924658/da01fa28-3fe7-44ab-0d25-9d851eecca6c.png) ![スクリーンショット 2021-06-29 22.54.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/924658/4509cd1b-407b-cb63-080d-7a3b595f0362.png) ![スクリーンショット 2021-06-29 22.57.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/924658/0d6ef18e-3022-3150-b7f1-dc731ea86041.png)

左から、ボトムナビゲーション、タブバー、ドロワー


#### 進むナビゲーション
階層を連続的に進む、フロー（手順的なステップ）を持つ、またはアプリ間での画面移動を指す

* カード、リスト、画面リストなどのコンテンツコンテナ
* 別の画面に進むボタン
* アプリ内検索
* コンテンツ内リンク

#### 戻るナビゲーション
進むナビゲーションで遷移した要素を、（時系列または階層的に）逆方向に戻るナビゲーション

## 色、タイポグラフィ、音、図像学、形状
トピック的には面白かったのですが、マテリアルデザインの説明という感じではなかったので省略

## モーション
遷移するときに、要素同士がどのように関係しているかをユーザに（それとなく）示します
「直感的なアプリ」はモーションをうまく使って、説明的ではないアプリを作り上げている気がします

#### アプリ内の位置を表現するモーション
* プルダウンメニューやコンテキストメニューがふわっと出てくる
* タブを切り替えるときに、左右に画面がスワイプする
* 新しい画面を開くときに、浮き上がるように出てくる
    * 加えて、強調のために背景を小さくグレーアウトすることもある

プラットフォームで何もしなくても提供されていることが多い気がします

#### ユーザにフィードバックするモーション
* twitterのように、画面を上方向にスクロールしようとすると、更新画面が少しずつ出てくる
    * ボタンのような物理的なインタフェースや、マウスジェスチャとは異なる
* 画面をスワイプすると指に従って画面が動くが、離すとキリのいい場所に戻る
    * スワイプができることを示唆している
* 商品アイコンがカートアイコンの方に飛んでいく
    * 似たところだと、Amazonアプリは商品をカートに入れると、バイブレーションの後にカートの数字がじっくりカウントアップする

「こういう操作ができる」、「ユーザの操作によってアプリにこういう変化があった」をアニメーションで表しています

#### 遊び心のモーション
* アイコンをタップすると愉快に動く
* ローディングやエラー画面で、イラストアニメーションを使う
* 要素を移動するときに、弾力的に（飛び跳ねる、重みがあるような）アニメーションをする

こちらは上級テクニックで、おおよそ自分で実装する必要がありそうです。開発優先度は低そうですが、飽きずに長く使ってもらうのに役立ちそうです

#### やらないこと
* 複数の要素を同時に動かさない
* 複数の要素を時間的にバラバラに動かさない

いずれにせよ、 **ユーザがどこに注目して良いかわからなくなるようなアニメーションはすべきでない**、ということだと思います

# 補記
Google公式がマテリアルデザインに従って作ったサンプルアプリがいくつか用意されています

[Material Studies](https://material.io/design/material-studies/about-our-material-studies.html#color)

少々アニメーションがリッチすぎるような気はしますが、マテリアルデザインを守った上で、どのように個性を出すかを考えたものです
個人的には、「みんながマテリアルデザインに従ったら、みんな同じようなアプリになるんじゃない？」と思っていたので、良い刺激をもらえました

例えばアプリで個性を出すとしたら下記のような点かと思います

* 画面構成
    * ユーザにどの順番で何を、どのように見せるか
* 配色
    * どの色をメインに据えて、その色にどのような意味づけをするか
* フォント
    * 本文はサンセリフ体が基本ですが、見出しやポイントは装飾的な文字を使うことも
* 遊び
    * 画像を石積みのようにランダムにレイアウトする
    * 弾力のあるアニメーションを使う
* 高さの表現
    * 影を使うのか、透明度や色の濃淡で差をつけるのか

# まとめ
以上、GoogleのMaterial Design Guidelinesを一通り読んでまとめてみました
次はAppleのHuman Interface Guidelinesを読んで考え方の差を見てみたいですね