ActionBarのメニューにCheckBoxを表示する
前置き
ActionBar
では、メニューをすべて表示することができなかったり"showAsAction="never"
を設定したメニューがある場合、一部のメニューをActionBar
右端のドロップダウンに格納することがあります。
Andorid Developersではこの機能をAction Overflowと呼んでいます。
Action Overflowに関する細かい機能名称などが見つけられなかったため、この記事ではオーバーフローに格納されているメニューを「オーバーフローメニュー」と呼ぶことにします。
http://developer.android.com/design/patterns/actionbar.html
オーバーフローメニューの活用
ActionBarのオーバーフローメニューにはチェックボックスやラジオボタンを表示することができます。 メニューと違って常時表示されないデメリットはありますが、タイトルが表示されるのでどのような機能かわかりやすく、アイコンを用意しなくても良いというメリットもあります。
下の画像はPlayストアアプリでの例です。
以下、チェックボックスとラジオボタン、それぞれの実装について説明します。
サンプルではappcompat-v7
版のActionBarを使用しています。
チェックボックスの実装
チェックボックスを利用する際、オーバーフローメニュー以外ではチェックボックスが表示されない事に気をつけてください。
<item>
要素にshowAsAction="never"
を設定しておくことで確実にオーバーフローメニューにすることができますが、
showAsAction="always"
やshowAsAction="ifRoom"
を定義するとチェックボックスが表示されなくなります。
チェックボックス自体はメニューを定義しているxmlにandroid:checkable="true"
を加えるだけで表示されます。
最初からチェック済みにしたい場合はandroid:checked="true"
を定義してください。
<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);
}
````
以下の様な表示になります。
ラジオボタンの実装
ラジオボタンを使うといくつかのオーバーフローメニューからひとつを選ばせるようなUIを作ることができます。
チェックボックス同様、オーバーフローメニュー以外ではラジオボタンが表示されないことに注意してください。
各<item>
要素にはshowAsAction="never"
を指定する必要があります。
ラジオボタンでは、選択肢となる<item>
要素の親として<group>
を定義します。
この<group>
要素にandroid:checkableBehavior="single"
を定義することで、checked
状態になる<item>
要素をひとつだけに限定することができます。
このとき、各<item>
要素にはandroid:checkable="true"
を定義するとチェックボックスが表示されてしまうので注意してください。
また、特定の<item>
を最初から選択状態にしたい場合はその<item>
にandroid:checked="true"
を定義してください。
<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)
された状態になるため、選択された要素の状態のみ反映すれば良いことになります。
@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); }
以下のような表示になります。