3.0で入手した新しいPopupMenuは本当に気に入っていますが、メニュー項目の横にアイコンを表示できません。以下の.xmlからメニューを拡張しています:
<item Android:id="@+id/menu_delete_product"
Android:icon="@drawable/sym_action_add"
Android:title="delete"
Android:showAsAction="ifRoom|withText" />
<item Android:id="@+id/menu_modify_product"
Android:icon="@drawable/sym_action_add"
Android:title="modify"
Android:showAsAction="ifRoom|withText" />
<item Android:id="@+id/menu_product_details"
Android:icon="@drawable/sym_action_add"
Android:title="details"
Android:showAsAction="ifRoom|withText" />
このコードでは:
image.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PopupMenu pop = new PopupMenu(getActivity(), v);
pop.getMenuInflater().inflate(R.menu.shelves_details_menu, pop.getMenu());
pop.show();
}
});
アイコンが表示されません
少し冒険したい場合は、GoogleのPopupMenuのソースコードをご覧ください。独自のクラス、つまりGoogleのPopupMenuクラスと同じMyPopupMenuを作成しますが、少し変更を加えます。
PopupMenuのコンストラクターで:
public MyPopupMenu(Context context, View anchor) {
// TODO Theme?
mContext = context;
mMenu = new MenuBuilder(context);
mMenu.setCallback(this);
mAnchor = anchor;
mPopup = new MenuPopupHelper(context, mMenu, anchor);
mPopup.setCallback(this);
mPopup.setForceShowIcon(true); //ADD THIS LINE
}
setForceShowIconメソッドを使用して、強制的にアイコンを表示します。必要に応じて、パブリックメソッドを公開してこのフラグを設定することもできます。
Gaelan Bolgerが提供するソリューションへの貢献。 「IllegalAccessException:許可されていないフィールドへのアクセス」が発生した場合、このコードを使用します。
PopupMenu popup = new PopupMenu(mContext, view);
try {
Field[] fields = popup.getClass().getDeclaredFields();
for (Field field : fields) {
if ("mPopup".equals(field.getName())) {
field.setAccessible(true);
Object menuPopupHelper = field.get(popup);
Class<?> classPopupHelper = Class.forName(menuPopupHelper
.getClass().getName());
Method setForceIcons = classPopupHelper.getMethod(
"setForceShowIcon", boolean.class);
setForceIcons.invoke(menuPopupHelper, true);
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
prepareMenu(popup.getMenu());
popup.show();
テキスト
リフレクションを使用してアイコンを表示できました。これは最もエレガントなソリューションではないかもしれませんが、機能します。
try {
Class<?> classPopupMenu = Class.forName(popupMenu
.getClass().getName());
Field mPopup = classPopupMenu.getDeclaredField("mPopup");
mPopup.setAccessible(true);
Object menuPopupHelper = mPopup.get(popupMenu);
Class<?> classPopupHelper = Class.forName(menuPopupHelper
.getClass().getName());
Method setForceIcons = classPopupHelper.getMethod(
"setForceShowIcon", boolean.class);
setForceIcons.invoke(menuPopupHelper, true);
} catch (Exception e) {
e.printStackTrace();
}
サブメニューモデルを使用できます。そのため、ポップアップメニューを表示するメソッドを記述する必要はありません。自動的に表示されます。ご覧ください:
menu.xml
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android" >
<item
Android:id="@+id/action_more"
Android:icon="@Android:drawable/ic_menu_more"
Android:orderInCategory="1"
Android:showAsAction="always"
Android:title="More">
<menu>
<item
Android:id="@+id/action_one"
Android:icon="@Android:drawable/ic_popup_sync"
Android:title="Sync"/>
<item
Android:id="@+id/action_two"
Android:icon="@Android:drawable/ic_dialog_info"
Android:title="About"/>
</menu>
</item>
</menu>
mainActivity.Javaで
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
結果は次のとおりです。
メソッドpopup.show()を使用する前に、MenuPopupHelperインスタンスを作成し、メソッドsetForceShowIcon(true)を呼び出します。
try {
Field mFieldPopup=popupMenu.getClass().getDeclaredField("mPopup");
mFieldPopup.setAccessible(true);
MenuPopupHelper mPopup = (MenuPopupHelper) mFieldPopup.get(popupMenu);
mPopup.setForceShowIcon(true);
} catch (Exception e) {
}
私が見つけた最も簡単な方法は、MenuBuilder
とMenuPopupHelper
を使用することです。
MenuBuilder menuBuilder =new MenuBuilder(this);
MenuInflater inflater = new MenuInflater(this);
inflater.inflate(R.menu.menu, menuBuilder);
MenuPopupHelper optionsMenu = new MenuPopupHelper(this, menuBuilder, view);
optionsMenu.setForceShowIcon(true);
// Set Item Click Listener
menuBuilder.setCallback(new MenuBuilder.Callback() {
@Override
public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
switch (item.getItemId()) {
case R.id.opt1: // Handle option1 Click
return true;
case R.id.opt2: // Handle option2 Click
return true;
default:
return false;
}
}
@Override
public void onMenuModeChange(MenuBuilder menu) {}
});
// Display the menu
optionsMenu.show();
menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item
Android:id="@+id/opt1"
Android:icon="@mipmap/ic_launcher"
Android:title="option 1" />
<item
Android:id="@+id/opt2"
Android:icon="@mipmap/ic_launcher"
Android:title="option 2" />
</menu>
MenuPopupHelper.setForceShowIcon(true)
を使用して、このためのネイティブソリューションを見つけました。
private void createMenu(int menuRes, View anchor, MenuBuilder.Callback callback) {
Context context = anchor.getContext();
NavigationMenu navigationMenu = new NavigationMenu(context);
navigationMenu.setCallback(callback);
SupportMenuInflater supportMenuInflater = new SupportMenuInflater(context);
supportMenuInflater.inflate(menuRes, navigationMenu);
MenuPopupHelper menuPopupHelper = new MenuPopupHelper(context, navigationMenu, anchor);
menuPopupHelper.setForceShowIcon(true);
menuPopupHelper.show();
}
private void initMenu(View view) {
view.findViewById(R.id.myButton).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
createMenu(R.menu.help_menu, view, new MenuBuilder.Callback() {
@Override
public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
switch (item.getItemId()) {
case R.id.id1:
// Do something
break;
case R.id.id2:
// Do something
break;
case R.id.id3:
// Do something
break;
}
return true;
}
@Override
public void onMenuModeChange(MenuBuilder menu) {
}
});
}
});
}
PopupMenuはアイコンを表示しません。 ActionBarを使用できます。
上記のソリューションのいくつかは、リフレクションハックで機能しますが、
これを共有するだけです:最近同じ問題に遭遇しましたが、よりカスタマイズされたもの(メニューにカスタムビューを追加)を作成したいので、次のライブラリを作成しました。
リフレクションの使用に沿って、MenuPopupHelper
を使用する必要なしに、以下を追加できます。
if (popup.getMenu() instanceof MenuBuilder) {
//noinspection RestrictedApi
((MenuBuilder) popup.getMenu()).setOptionalIconsVisible(true);
}
メニューを膨らませる前に