ActionBarのメニューにCheckBoxを表示する

# 前置き
`ActionBar`では、メニューをすべて表示することができなかったり`"showAsAction="never"`を設定したメニューがある場合、一部のメニューを`ActionBar`右端のドロップダウンに格納することがあります。
Andorid Developersではこの機能をAction Overflowと呼んでいます。
Action Overflowに関する細かい機能名称などが見つけられなかったため、この記事ではオーバーフローに格納されているメニューを「オーバーフローメニュー」と呼ぶことにします。
http://developer.android.com/design/patterns/actionbar.html

# オーバーフローメニューの活用
ActionBarのオーバーフローメニューにはチェックボックスやラジオボタンを表示することができます。
メニューと違って常時表示されないデメリットはありますが、タイトルが表示されるのでどのような機能かわかりやすく、アイコンを用意しなくても良いというメリットもあります。

下の画像はPlayストアアプリでの例です。
![Playストアでの例](https://qiita-image-store.s3.amazonaws.com/0/48019/eb3f0461-c22d-017c-758f-fdddb88aa87f.png)

以下、チェックボックスとラジオボタン、それぞれの実装について説明します。
サンプルでは`appcompat-v7`版のActionBarを使用しています。

# チェックボックスの実装
チェックボックスを利用する際、**オーバーフローメニュー以外ではチェックボックスが表示されない**事に気をつけてください。
`<item>`要素に`showAsAction="never"`を設定しておくことで確実にオーバーフローメニューにすることができますが、
`showAsAction="always"`や`showAsAction="ifRoom"`を定義するとチェックボックスが表示されなくなります。
チェックボックス自体はメニューを定義しているxmlに`android:checkable="true"`を加えるだけで表示されます。
最初からチェック済みにしたい場合は`android:checked="true"`を定義してください。

```menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MyActivity" >
    <item android:id="@+id/action_checkbox"
        android:title="チェックボックス"
        android:checkable="true"
        app:showAsAction="never" />
</menu>
```

最も注意すべき点として、**チェックボックスの状態変更をソースコード上で行う必要がある**ことに気をつけてください。
また、チェックボックスの状態は`MenuItem.isChecked()`で取得できますが、ユーザ操作がチェックボックスに反映された後かどうかを意識する必要があります。

````MyActivity.java
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // メニュー生成
        getMenuInflater().inflate(R.menu.menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_checkbox) {
            // チェックボックスの状態変更を行う
            item.setChecked(!item.isChecked());
            // 反映後の状態を取得する
            boolean checked = item.isChecked();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
````

以下の様な表示になります。
![Screenshot_2014-08-31-15-13-57.png](https://qiita-image-store.s3.amazonaws.com/0/48019/8fbe2738-6122-2647-3bd7-03c916cee11f.png)


# ラジオボタンの実装
ラジオボタンを使うといくつかのオーバーフローメニューからひとつを選ばせるようなUIを作ることができます。
チェックボックス同様、**オーバーフローメニュー以外ではラジオボタンが表示されない**ことに注意してください。
各`<item>`要素には`showAsAction="never"`を指定する必要があります。

ラジオボタンでは、選択肢となる`<item>`要素の親として`<group>`を定義します。
この`<group>`要素に`android:checkableBehavior="single"`を定義することで、`checked`状態になる`<item>`要素をひとつだけに限定することができます。
このとき、各`<item>`要素には`android:checkable="true"`を定義するとチェックボックスが表示されてしまうので注意してください。
また、特定の`<item>`を最初から選択状態にしたい場合はその`<item>`に`android:checked="true"`を定義してください。


```menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MyActivity">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/action_radio1"
            android:title="ラジオ1"
            app:showAsAction="never" />
        <item
            android:id="@+id/action_radio2"
            android:title="ラジオ2"
            app:showAsAction="never" />
    </group>

</menu>
```

ラジオボタンでもチェックボックス同様、**状態変更をソースコード上で行う必要がある**ことに気をつけてください。
ただし、`android:checkableBehavior="single"`を定義している場合、`<group>`内のどれかひとつが`MenuItem#setChecked(true)`されたときに他の`MenuItem`は`MenuItem#setChecked(false)`された状態になるため、選択された要素の状態のみ反映すれば良いことになります。

```MyActivity.java
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        switch (id){
            case R.id.action_radio1:
                item.setChecked(!item.isChecked());
                Toast.makeText(this,"action_radio1",Toast.LENGTH_SHORT).show();
                return true;
            case R.id.action_radio2:
                item.setChecked(!item.isChecked());
                Toast.makeText(this,"action_radio2",Toast.LENGTH_SHORT).show();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }
```

以下のような表示になります。
![Screenshot_2014-08-31-15-30-21.png](https://qiita-image-store.s3.amazonaws.com/0/48019/9cc85a2b-5a3f-96eb-14ed-337a401907a7.png)