NavigationViewを使ってGoogle Play風のメニューを作る【Android Design Support Library】

# 概要
最近Googleから[Design Support Library](http://android-developers.blogspot.jp/2015/05/android-design-support-library.html)が公開されましたね。

こいつを使うことで、Googleのアプリで使われているマテリアルデザイン用のUIが簡単に利用できます。

まだ情報も少ないので、今回はNavigationViewの使い方を少し詳しくまとめてみました。


ソースコードはGithubにあげてあるので、よかったら参考にしてください。(他のViewも実装してます)
https://github.com/chuross/DesignSupportLibrarySample

# NavigationViewとは？
Google Play等のGoogle製アプリで使われているナビゲーションドロワーを実装できるViewです。

これを使う事で、今まで自分でRelativeLayoutをListViewにaddHeaderViewするような悲しい実装をこいつ一つでできるようになりました。

こんな感じ
![device-2015-06-03-042350.png](https://qiita-image-store.s3.amazonaws.com/0/20629/94d70a7f-be68-7f0c-e5ab-e0fe461b5697.png)

# 特徴
- メニューのXMLを書くと、そこからViewを自動生成してくれる
- ヘッダーレイアウトXMLとメニューXMLの指定をレイアウトXML上で表現できる
 - 自分でfindViewByIdした後にヘッダーレイアウトXMLやメニューXMLを指定するコードを書く必要がない
- クリックイベントの処理もActivityに配置するメニュー感覚で処理できる

# 作り方
前置きは以上で、ここから実際にDesign Support Libraryの導入からGoogle Play風のドロワーを作るところまで紹介します。

## 導入
### Android Support Repositoryの更新
Android SDK　Managerを起動し、Android Support Repositoryを更新します。

![snapshot.png](https://qiita-image-store.s3.amazonaws.com/0/20629/fa7c24ad-5933-af42-6844-5eeb7a1b6194.png)

**Extras**の中にあるよ！

### build.gradleに追加
自分のプロジェクトのdependenciesにDesign Support Libraryを追加します

`compile 'com.android.support:design:22.2.0'`

例)

```groovy
dependencies {
    // android standard lib
    compile 'com.android.support:design:22.2.0'
    compile 'com.android.support:appcompat-v7:22.2.0'
    ...
}
```

## 実装
### DrawerLayoutの中にNavigationViewを記述する
`app:headerLayout`にはヘッダーのレイアウトのリソースIDを指定します。
`app:menu`には表示する項目のメニューのリソースIDを指定します。

```xml
<android.support.v4.widget.DrawerLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true">

    <!-- your content layout -->

    <android.support.design.widget.NavigationView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            app:headerLayout="@layout/drawer_header"
            app:menu="@menu/drawer"/>
</android.support.v4.widget.DrawerLayout>
```

### ヘッダーのXMLを作成する
基本的にはヘッダーに表示したいレイアウトXMLをいつも通りに書いていけば問題ないです。

例)

```drawer_header.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:background="@color/primary_dark_material_light" />
```

### メニューのXMLを作成する
Androidのmenu xmlのルールに沿って記述していきます。

`group`はメニュー項目の集合を表します。
`<item> -> <menu> -> <item>`の入れ子を使うとサブヘッダーを表示できます。

```drawer.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <group
        android:checkableBehavior="single">
        <item
            android:id="@+id/menu_home"
            android:icon="@android:drawable/ic_menu_gallery"
            android:title="ホーム" />
        <item
            android:icon="@android:drawable/ic_menu_gallery"
            android:title="視聴履歴" />
        <item
            android:icon="@android:drawable/ic_menu_gallery"
            android:title="ブックマーク" />
        <item
            android:icon="@android:drawable/ic_menu_gallery"
            android:title="マイページ" />
        <item
            android:icon="@android:drawable/ic_menu_gallery"
            android:title="検索" />
    </group>
    <item
        android:title="その他">
        <menu android:checkableBehavior="single">
            <item
                android:title="お知らせ" />
            <item
                android:title="このアプリについて" />
            <item
                android:title="設定" />
        </menu>
    </item>
</menu>
```

### 実行
実行するとこんな感じのドロワーメニューが表示されれば完成です。
あとは好みでガシガシカスタマイズしていきましょう。

![device-2015-06-03-042035.png](https://qiita-image-store.s3.amazonaws.com/0/20629/3f17d69f-498f-980c-e5fc-b2d5d1ffbb9c.png)

# おまけ
待って！Google Playの方はサブヘッダー無いよ！
サブヘッダー表示したくない時にはどうすればいいの？と思った人もいるかと思います。

今回の例の場合のように、サブヘッダーが表示している文字列に意味はないので消したい、
しかし上のメニューと線で区切りたいというケースはあると思います。

最初の方に貼ったデベロッパーブログには特に言及されてなかったのでコード読んで調べてみました。

NavigationViewの中にNavigationMenuPresenterというクラスがあり、どうやらそいつが内部メニュー項目の生成を行っているようです。

実装方法は単純で、groupにidを振ると別物のグループとして認識してセパレートを自動的に配置してくれるようです。便利ですね。

```xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <group
        android:id="@+id/menu_main"
        android:checkableBehavior="single">
        <item
            android:id="@+id/menu_home"
            android:icon="@android:drawable/ic_menu_gallery"
            android:title="ホーム" />
        <item
            android:icon="@android:drawable/ic_menu_gallery"
            android:title="視聴履歴" />
        <item
            android:icon="@android:drawable/ic_menu_gallery"
            android:title="ブックマーク" />
        <item
            android:icon="@android:drawable/ic_menu_gallery"
            android:title="マイページ" />
        <item
            android:icon="@android:drawable/ic_menu_gallery"
            android:title="検索" />
    </group>
    <group
        android:id="@+id/menu_other"
        android:checkableBehavior="single">
        <item
            android:title="お知らせ" />
        <item
            android:title="このアプリについて" />
        <item
            android:title="設定" />
    </group>
</menu>
```

サブヘッダーが無くなった！

![device-2015-06-03-041454.png](https://qiita-image-store.s3.amazonaws.com/0/20629/416c9d05-0ba5-ac3f-e3ac-4c219c3c534c.png)