「本記事は Android Developer Relations チームの Chris Banes と Nick Butcher が 10 月 24 日に Android Developers blog に投稿した「Implementing Material Design in Your Android app 」という記事を元に、翻訳・作成しています。詳しくは元記事をご覧ください。 - 荒木」
マテリアル デザイン はマルチスクリーンの世界にむけた、ビジュアル、インタラクション、モーションデザインの包括的なアプローチです。Android 5.0 Lollipop とアップデートされたサポート ライブラリは、マテリアル UI の作成をサポートします。以下にあなたのアプリに導入可能なウィジェットや API、そしてマテリアル デザインの主な要素について説明します。
タンジブル サーフェス
マテリアル デザインにおける UI は、デジタルの紙とインク でできています。サーフェスとそれが落とす影は、触れることができる範囲、触れたらどのように動くか、といったアプリケーションの構造を視覚的に表現しています。このデジタル化されたマテリアルは動いたり、拡張したり、変形したりすることで、柔軟な UI を形成します。
影の描写
サーフェスの位置と深度は、光のあたり具合や影に微妙な影響を与えます。新しい elevation プロパティを使用すれば、ビューの Z 軸における位置を指定できます。位置情報を元に、フレームワークはリアルタイムでそのビューよりも後ろにあるアイテムに影を落とします。レイアウト内で elevation の設定が行えます(単位: dip)。
<ImageView …
android:elevation="8dp" />
また、ViewCompat の getElevation()/setElevation()(shim を利用)を使用して、コード上で設定することもできます。ビューが落とす影の形は基本的に背景の情報から算出されたアウトラインによって決まります。たとえば円形の drawable を floating action button の背景として設定していた場合、適切な形の影を落とすということです。ビューが落とす影の形をより詳細に制御したい場合は、getOutline() で Outline をカスタマイズできる ViewOutlineProvider を設定することができます。
カード
カード は、特定の情報を持ったサーフェスを作成する一般的なパターンです。CardView サポート ライブラリがアウトラインと影を提供するので、カードの作成は簡単です(旧来のプラットフォームでも同様の挙動です)。
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!--カードのコンテンツ -->
</android.support.v7.widget.CardView>
カードの見た目をプラットフォームをまたいで統一するために、CardView は FrameLayout を拡張しており、elevation と角の丸みの半径のデフォルト値を設定します。これらは必要に応じて cardElevation と cardCornerRadius の属性を更新することでカスタマイズできます。UI に奥行きをもたせる方法はカードだけではないので、カードばかり使いすぎないように 気をつけましょう!
印刷物のようなデザイン
コンテンツが主役になるよう、マテリアル デザインは印刷物のデザインの原則にのっとり、すっきりとしたシンプルなレイアウトを実現します。大胆かつ考えぬかれた色の選択、意図的な余白、良質なタイポグラフィと、しっかりとしたベースライングリッドによって階層、意義、焦点が生み出されます。
タイポグラフィ
Android 5.0 ではシステム フォント Roboto がアップデートされ、画面サイズにこだわらずテキストを美しく、クリアに表示します。ミディアムウェイトが追加され(android:fontFamily="sans-serif-medium")、新しい TextAppearance スタイルは推奨されているタイポグラフィ スケール にのっとり、読みやすさとコンテンツの密度のバランスをとります。たとえば、android:textAppearance="@android:style/TextAppearance.Material.Title" と設定するだけで 「Title」のスタイルを適用できます。これらのスタイルは AppCompat サポート ライブラリを通じて、旧来のプラットフォームでも使用できます(“@style/TextAppearance.AppCompat.Title” など)
カラー
アプリのカラーパレット はブランディングや個性をもたらす要素です。下記のようなテーマ属性を用いて UI のコントロール要素を簡単に色付けできるようにしました。
colorPrimary: アプリのプライマリ色です。Action Bar の背景、最近のタスクのタイトル、エッジ効果などに使われます
colorAccent: プライマリ色を補足する明るい色です。EditText や Switch などのフレームワーク コントロールに使われます
colorPrimaryDark: プライマリ色の暗いバリエーションです。Status Bar に使われます
コントロール要素の色付けをよりきめ細かく行うには下記の属性を参照してください: colorControlNormal、colorControlActivated、colorControlHighlight、colorButtonNormal、colorSwitchThumbNormal、colorEdgeEffect、statusBarColor、navigationBarColor
AppCompat は上記の機能の多くを提供し、Lollipop 搭載前のプラットフォームでもコントロール要素の色付けを可能にします。
ダイナミックカラー
マテリアル デザインでは画像にあわせて色を流動的に使い分けることを推奨しています。特に色彩豊かな画像を採用している場合に有効です。新しいパレット サポート ライブラリは、画像からいくつかの色を抽出して UI コントロール要素のスタイルを抽出した色に合わせることを可能にし、ユーザーは没入感を得ることができます。抽出されたパレットには、明るい色、抑えた色、読みやすさを考慮したテキスト色が含まれます。
Palette.generateAsync(bitmap,
new Palette.PaletteAsyncListener() {
@Override
public void onGenerated(Palette palette) {
Palette.Swatch vibrant =
palette.getVibrantSwatch();
if (swatch != null) {
// 明るい色があるときは
// タイトルの TextView を更新する
titleView.setBackgroundColor(
vibrant.getRgb());
titleView.setTextColor(
vibrant.getTitleTextColor());
}
}
});
リアリティのある動き
タンジブル サーフェスは映画の場面切り替えのように突然どこからともなく現れるものではなく、継続性を保ちます。その動きはユーザーの注意を促し、空間的な関係性を構築します。マテリアルはユーザーのタッチに反応し、もたらされる変化はタッチされた箇所を起点として広がります。ユーザーが理解しやすいように、すべての動きはなじみがあり意味あるものになっています。
Activity と Fragment の遷移
2 つの画面で共通する 「shared elements」(共有要素) を宣言することで、異なる状態への遷移をスムーズに行うことができます。
album_grid.xml
…
<Imageview
…
android:transitionname="@string/transition_album_cover" />
album_details.xml
…
<Imageview
…
android:transitionname="@string/transition_album_cover" />
AlbumActivity.java
Intent intent = new Intent();
String transitionName = getString(R.string.transition_album_cover);
…
ActivityOptionsCompat options =
ActivityOptionsCompat.makeSceneTransitionAnimation(activity,
albumCoverImageView, // 遷移がはじまるビュー
transitionName // 遷移先のビューの transitionName
);
ActivityCompat.startActivity(activity, intent, options.toBundle());
ここでは2つの画面で同じ transitionName を定義します。新しい Activity が開始されると、この遷移は自動的に処理されます。また、要素を共有する以外にも、遷移開始時 と終了時 の演出を行うことが可能です。
リップル効果
マテリアルは ink ripple surface reaction でユーザーのタッチに反応します。Theme.Material を使用するか継承する場合、Button などのコントロールはデフォルトで ink ripple の反応をみせます(?android:selectableItemBackground も同様です)。drawable にリップル効果を追加するには、下記のようにRipple 要素を設定します。
<ripple
xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/accent_dark">
<item>
<shape android:shape="oval">
<solid android:color="?android:colorAccent" />
</shape>
</item>
</ripple>
タッチポイントからリップル効果がはじまるよう、カスタムビューでは View#drawableHotspotChanged コールバックにて、drawable にタッチ位置を伝える必要があります。
StateListAnimator
また、マテリアルは磁石がユーザーの指に吸いつくように持ち上がります 。このような効果を実現するためには、translationZ 属性を活用します。これは elevation と似ていますが、一時的な効果をもたらすために利用します(Z = elevation + translationZ というように)。新しい stateListAnimator 属性を活用すれば、ユーザーのタッチに反応して translationZ を簡単に調整することが可能です(Buttons はデフォルトでこのように動作します)。
layout/your_layout.xml
<Imagebutton ...
android:statelistanimator="@anim/raise" />
anim/raise.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:state_pressed="true">
<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyname="translationZ"
android:valueto="@dimen/touch_raise"
android:valuetype="floatType" />
</item>
<item>
<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyname="translationZ"
android:valueto="0dp"
android:valuetype="floatType" />
</item>
</selector>
Reveal
新しいコンテンツを表示させる際、マテリアル デザインの特徴を生かした遷移方法の 1 つが、拡大する円形マスクを利用したものです。この方法は、タッチした位置から外に向かって放射状に広がるので 、ユーザーのタッチポイントがすべてのトランジションの始点であることを補強しています。これを実現するためには次の Animator を使用します。
Animator reveal = ViewAnimationUtils.createCircularReveal(
viewToReveal, // Reveal するための新しいビュー
centerX, // マスク中心の x 座標
centerY, // マスク中心の y 座標
startRadius, // 開始時のマスクの半径
endRadius); // 完了時のマスクの半径
reveal.start();
Interpolator
モーションは計算しつくされ、俊敏で正確であるべきです。ゆっくりと始まり、ゆっくりと終わる典型的な遷移とは異なり、マテリアル デザインにおけるオブジェクトは素早く動き始め、ゆっくりと最終位置につきます。オブジェクトは遷移動作時間のうち、より長い時間、最終位置付近に存在します。結果としてユーザーは遷移動作が終わるのを待つ必要がなくなり、モーション化によるマイナス効果は最小限に抑えられます。このような動作を可能にするのは、新しく追加された fast-in-slow-out interpolator です。
要素が画面を出たり入ったりする場合、ピーク速度で行うのが好ましい ですが、要素が画面外に出る際には fast-out-linear-in interpolator を、画面内に入る際には linear-out-slow-in interpolator を参考にしてください。
適応性の高いデザイン
マテリアル デザインにおける最終的な核となるコンセプトは、時計から大型テレビまでのさまざまな形・大きさのデバイスに適応するデザインを作ることです。このデザインのテクニックによって、それぞれのデバイスが共通のシステムを異なるビューで具現化するというビジョンの実現が可能になりました。各デバイスの画面の大きさや操作方法に適応するように各ビューを調整する一方で、色、アイコン、階層構造、各要素の空間的関係性には統一感をもたせます。マテリアル デザイン システムは、拡張可能なデザインを作成するのに役立つ柔軟なコンポーネントとパターンを提供します。
Toolbar
Toolbar は Action Bar を一般化させたもので、同様の機能を備えつつ、より高い柔軟性を提供します。通常の Action Bar と異なる点は、Toolbar は階層内のビューの 1 つであるということです。そのため、Toolbar のインスタンスは好きなところに配置することができ、他のビューと共存します。さらに、動きを与えたり、スクロール イベントに反応させたりもできます。Activity.setActionBar() をコールすることで、Toolbar を Activity の Action Bar として機能させることもできます。
上記の例では、青い Toolbar は高さが拡張され、コンテンツがオーバーレイしており、ナビゲーションボタンを提供しています。また、リスト部分と詳細ビューには、さらに 2 つの toolbar が使われていることにも注目してください。
Toolbar の導入については、こちらの記事 を参照してください。
マテリアル化を進めましょう
マテリアル デザインは理解しやすく、美しく、適応性の高い、モーションにあふれたアプリを作ることを支援します。この記事が、みなさまがこれらの原則をアプリに適用されるきっかけとなり、その実現のために新しい API と互換用の API を活用するための手がかりとなることを願っております。
Posted by 荒木佑一 Developer Relations Team