Edited at

support.v4のActionProviderを使ってActionBarにサブメニューを追加したい

More than 3 years have passed since last update.

サブメニューが表示されなかったりしてハマったのでメモ。


Activityの書き方


YourActivity.java

public class YourActivity extends ActionBarActivity {

/* hogehoge */

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
MenuItemCompat.setActionProvider(menu.findItem(R.id.awesome_item), new YourActionProvider(this));
return super.onCreateOptionsMenu(menu);
}

/* hogehoge */
}


ActivityのonCreateOptionsMenuでメニューアイテムの初期化を行う。

MenuItemCompatを使って指定したアイテムにActionProviderを割り当てます。


menuのXMLファイルの書き方

次にR.menu.mainの内容をみてみます


main.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=".MainActivity">
<item
android:id="@+id/awesome_item"
android:icon="@android:drawable/ic_menu_camera"
app:showAsAction="ifRoom"
android:title="@android:string/cancel"
app:actionProviderClass="com.stenpel.awesome.app.common.CameraActionProvider" />
</menu>

menuの中にitemがひとつだけあります。

YourActivityでActionProviderを割り当てられている、R.id.awesome_itemですね。

showAsAction,actionProviderClassはandroidではなく独自に定義したappを指定します。appの部分は好きな文字列でOKです。


独自拡張したActionProviderの書き方

次は独自のActionProviderを書きます


YourActionProvider.java

public class CameraActionProvider extends android.support.v4.view.ActionProvider {

/**
* Creates a new instance.
*
* @param context Context for accessing resources.
*/

public CameraActionProvider(Context context) {
super(context);
}

@Override
public View onCreateActionView() {
return null;
}

@Override
public boolean hasSubMenu() {
return true;
}

@Override
public void onPrepareSubMenu(SubMenu subMenu) {
subMenu.clear();
MenuInflater inflater = new MenuInflater(getContext());
inflater.inflate(R.menu.awesome_provider_menu, subMenu);
}
}


ActionProviderでは表示したいサブメニューを初期化を担当します。

初期化するメソッドがonPrepareSubMenuです。

この中でR.menu.awesome_provider_menuというxmlを実体化しています。

ちなみに、このonPrepareSubMenuはMenuItemが選択されるたびに呼び出されるためsubMenu.clear()でサブメニューを一旦すべて消しています。これをやっておかないとMenuItemを選択されるたびにサブメニューアイテムが重複して追加されていってしまいます。


サブメニューのXMLファイルの書き方

最後に、サブメニュー一覧用のXMLを書きます。


awesom_provider_menu.xml

<?xml version="1.0" encoding="utf-8"?>

<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/awesome_provider_sub_menu_1"
android:title="@string/awesome_text_1"
android:icon="@android:drawable/ic_menu_camera" />
<item
android:id="@+id/awesome_provider_sub_menu_2"
android:title="@string/awesome_text_2"
android:icon="@android:drawable/ic_menu_compass" />
</menu>


ここは特に変わったところはない感じです。menuとitemを入れ子にして定義すればOKです。

動いてよかった。