読者です 読者をやめる 読者になる 読者になる

Material Designの目指すところとAndroid側の変更点

モバイルファースト室の @rejasupotaro です。

今年のGoogle I/OではAndroid One、Android L、Material Design、Android Ware、Android Auto、Android TV、Google Cloud Platform、Google Fitなどの発表がありました。弊社からは私と @sys1yagi@__gfx__ が参加したので、何回かに分けてGoogle I/Oの発表の内容を紹介します。

今回のテーマはMaterial Designです。内容は公式ドキュメントやセッション動画の要約や参考リンクからの引用を含みますが、筆者の考察や主観も含まれます。

Material Designとは

Material Designとは、Googleが発表したビジュアル、モーション、インタラクションのプラットフォームやデバイス間の包括的なガイドです。Material Designは、現実世界の素材をメタファーとすることでユーザにとって分かりやすく表現するための視覚言語です。

Gmailアプリの比較したのが下の図です。左が現在のGmailアプリで、右が新しいGmailアプリです。

f:id:rejasupotaro:20140708102937p:plain

タイポグラフィは見やすく、グリッドを調整して、サーフェスを一新されました。

フラットデザインの主眼は、視覚的な混乱を取り除くことにありました。でもそのおかげで、例えば影のような、スクリーンを見やすく、操作しやすくするためのディテールも取り去られてしまいました。Material Designでは、ピクセルは色と深さを持っています。リアルな光によって繋ぎ目を表現し、空間を分割し、動くパーツとして表現して、それ以外の無駄な装飾を省いています。

f:id:rejasupotaro:20140708102936p:plain

Material Designの目指すところ

今年のGoogle I/OでAndroid Ware、Android Auto、Android TVなどのプラットフォームの発表がありました。KeynoteでPichai氏はInternet of Things(モノのインターネット:家電や自動車など多種多様な「モノ」がインターネットにつながり、お互いに情報をやり取りすることで新しい価値を生み出すという概念)と掛けて、Android of Thingsと言っており、身の回りのあらゆるものにGoogleのプラットフォームを浸透させようとしています。そうなると、ユーザとのインタフェースになるデザインは今後さらに重要になってくると考えられます。

小さな画面で膨大な情報を扱うAndroid Wearにも、車の運転に注意力の大半を持っていかれるAndroid Autoにも、OSでありブラウザでもあるChromeでも、ユーザが迷わないためにプラットフォームやデバイスを超えてデザインをする必要があります。各プラットフォームがバラバラにデザインされるとユーザが混乱してしまうので、Material Designという統一的なデザインガイドラインを定めて、ユーザは一つのコンテキストを知っているだけで操作できるようにしようとしているのだと思います。ガイドラインを読むとMaterial Designは、インタフェースはシンプルに、タイポグラフィはどのデバイスでも見やすく、クロスプラットフォーム・マルチデバイスを意識して設計されているということが分かります。

クロスプラットフォームとMaterial Design

それでは、ウェブもiOSもAndroidも、同じデザインで作らなければならないのでしょうか。その疑問について Going responsive with the Google Play Apps Suite というセッションで、クロスプラットフォームでデザインをどうスケールさせるかという話が興味深かったです。

下の図は2012年のPlayアプリです。

f:id:rejasupotaro:20140708102944p:plain

アプリのデザインが他のものと統一されていないと感じるでしょう。プラットフォームごとにメンタルモデル、ルックアンドフィール、インタラクションに対して異なるアプローチをしていました。そのため、同じ機能のために何度もデザインをしていて、デザインをスケールさせることができませんでした。そこで、Playアプリ間でデザインを統一しようとしました。

統一するといっても単純に同じものにするということではありません。ウェブとアプリでは異なるインタラクションを持っています。なぜならウェブではユーザとシステムのインタフェースにマウスを使っています。インタラクションは異なっていますが、パターンは一貫している必要があります。

Playではサイドナビゲーションを使っています。下の図の左がウェブで右がアプリです。ウェブとアプリは同じタイプの情報を提供していますが、ウェブの方がスペースが広かったりするので、表示の仕方や中身を変えています。

f:id:rejasupotaro:20140708102940p:plain

タブは、ウェブから見た場合マウスではスワイプが困難なので、クリックで展開されるようにしています。

f:id:rejasupotaro:20140708102941p:plain

メニューボタンは、ウェブではロールオーバー時にメニュー表示するようになっています。しかし、デバイスにはロールオーバーはありません。iOSではメニューボタンを押したときにパネルが下からスライドしてくるようになっています。なぜならそれがiOSのパターンだからです。Androidではポップアップするようにしています。なぜならそれがAndroidのパターンだからです。

このように、インタラクションの表現はプラットフォームによって少しづつ変える必要があるのです。

f:id:rejasupotaro:20140708102942p:plain

f:id:rejasupotaro:20140708102943p:plain

私はMaterial Designが発表されたからといって、すべてのプラットフォームやデバイスでまったく同じ見た目やインタラクションにする必要はないと考えています。Material Designの良いところは積極的に取り入れつつ、自社サービスを使っているユーザが一番使いやすいデザインを模索して、実装していきたいと思います。

Android側の変更点

さて、そんなMaterial Designですが、Android L Developer Previewではマテリアルデザインのアプリを作るための機能追加やライブラリが提供されたので、それらの一部を紹介します。実際に実装する際には、Material Designの公式のガイドライン(Material Design - Google design guidelines)を一読することをオススメします。また、現在はPreviewなので今後APIや挙動は変わる可能性があるのでご注意ください。

Material Theme

Material Themeはウィジェットにカラーパレットをセットしたり、タッチフィードバックやアクティビティのトランジションなど、アプリに新しいスタイルを提供します。styleでMaterial Themeを継承することで使うことができます。

<resources>
    <style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
        <item name="android:colorPrimary">@color/primary</item>
        <item name="android:colorPrimaryDark">@color/primary_dark</item>
        <item name="android:colorAccent">@color/accent</item>
    </style>
</resources>

colorPrimaryやcolorPrimaryDarkなどを上書きすることでActionBarやStatusBarの色を変更することができます。

New Widgets

ListViewの新しいバージョンであるRecyclerViewと、情報の一片をカードとして表示するCardViewの二つのウィジェットが提供されています

RecyclerView

dependenciesに compile "com.android.support:recyclerview-v7:+" を追加してください。レイアウトマネージャを使って柔軟にアイテムのポジションを変えたり、デフォルトでビューの追加と削除のアニメーションが追加されています。RecyclerViewにはaddやremoveなどの操作にデフォルトでアニメーションが付きます。

<android.support.v7.widget.RecyclerView
    android:id="@+id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

データとのアダプターにRecyclerView.Adapterを使うようになりました。従来のgetViewを継承するスタイルからCreateしてBindするスタイルに変わっています。setOnItemClickListenerが実装されていなかったり、今までと違ってLayoutManagerを渡さないとクラッシュしたりと、ちょっと癖がありました。しかし、LayoutManagerを使うことで柔軟なレイアウトが組めそうです。

CardView

dependenciesに compile "com.android.support:cardview-v7:+" を追加してください。CardViewはFrameLayoutの拡張で、どのアプリでも統一した見た目で情報をカードとして表示することができます。CardViewに影を付けたり、角を丸くしたりすることができます。

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:elevation="@dimen/spacing_small"
    card_view:cardCornerRadius="@dimen/spacing_small">

    <ImageView
        android:id="@+id/list_item_photo"
        android:layout_width="match_parent"
        android:layout_height="180dp"
        android:scaleType="centerCrop" />

</android.support.v7.widget.CardView>

View Shadow

ビューに高さを表現するZプロパティが追加されました。これは影の大きさと並びに影響を与えます。ZプロパティはelevationとtranslationZから成り立っています。

Animations

UI操作のタッチフィードバック、ビューの状態の変更、アクティビティのトランジションのためのアニメーションのAPIが提供されました。

新しいアニメーションのAPIで以下のようなことができます。

  • タッチイベントに反応するタッチフィードバックアニメーション
  • ビューの表示・非表示を分かりやすくするアニメーション
  • アクティビティを遷移するときのアニメーション
  • より自然な動きを表現するカーブドモーション
  • ビューの状態の変化のアニメーション

SceneTransitionAnimation

Activity間でビューをSharedElementとして渡すことができるようになりました。ビューのidを指定したtransitionを定義して、styleでtransitionを上書きします。

<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- moveImage is used for the ImageViews which are shared -->
    <moveImage>
        <targets>
            <target android:targetId="@id/detail_photo" />
            <target android:targetId="@id/list_item_photo" />
        </targets>
    </moveImage>

</transitionSet>
<resources>
    <style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
        ...

        <item name="android:windowContentTransitions">true</item>
        <item name="android:windowSharedElementEnterTransition">
            @transition/grid_detail_transition
        </item>
        <item name="android:windowSharedElementExitTransition">
            @transition/grid_detail_transition
        </item>
    </style>
</resources>

定義したらstartActivityの引数にActivityOptionsをBundleとして渡します。

// ActivityOptionsに共有するビューのidを渡す
ActivityOptions activityOptions = ActivityOptions.makeSceneTransitionAnimation(
        activity,
        new Pair<View, String>(view.findViewById(R.id.list_item_photo),
                ArticleDetailActivity.VIEW_NAME_PHOTO),
        new Pair<View, String>(view.findViewById(R.id.list_item_title),
                ArticleDetailActivity.VIEW_NAME_TITLE));

// 呼び出すときに組み立てたActivityOptionsを渡す
private void openDetailActivity(Article article, View view) {
    startActivity(ArticleDetailActivity.createIntent(this, article),
            ArticleDetailActivity.createOption(this, view));
}

サンプルアプリケーション

新しいAPIを使ってアプリを書いてみました。懸念していたActionBarはほぼそのままで動いて良かったです。まだ至らぬ点があるのでアップデートしていこうと思っています。リポジトリはこちらです: rejasupotaro/MaterialDesignSample

f:id:rejasupotaro:20140708102947p:plain

f:id:rejasupotaro:20140708102946g:plain

全体のまとめ

  • Material Designは静止画で見るとフラットデザインっぽいですが、思想や使い心地は異なったものです
  • ウェブやiOSにもサービスを提供している場合は、どのようにMaterial Designを取り入れるのがユーザにとって一番良いのか考える必要があります
  • Android L Developer Previewは、まだプレビュー感が強いのでただちに移行するということはないが、ウォッチはしていた方が良いです

参考リンク

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/