ネイティブAPIを使用することはできません。そのようなビューを実装する回避策はありますか?
以前に投稿された回答は、一般的に言えばOKです。ただし、基本的にはオーバーフローメニューのデフォルトの動作は削除されます。さまざまな画面サイズで表示できるアイコンの数、および表示できないときにオーバーフローメニューにドロップされるアイコンの数など。上記を行うことで、多くの重要な機能を削除します。
より良い方法は、オーバーフローメニューにアイコンを直接表示するように指示することです。これを行うには、アクティビティに次のコードを追加します。
@Override
public boolean onMenuOpened(int featureId, Menu menu)
{
if(featureId == Window.FEATURE_ACTION_BAR && menu != null){
if(menu.getClass().getSimpleName().equals("MenuBuilder")){
try{
Method m = menu.getClass().getDeclaredMethod(
"setOptionalIconsVisible", Boolean.TYPE);
m.setAccessible(true);
m.invoke(menu, true);
}
catch(NoSuchMethodException e){
Log.e(TAG, "onMenuOpened", e);
}
catch(Exception e){
throw new RuntimeException(e);
}
}
}
return super.onMenuOpened(featureId, menu);
}
メニューxmlで、次の構文を使用してメニューをネストします。アイコン付きのメニューの取得を開始します
<item
Android:id="@+id/empty"
Android:icon="@drawable/ic_action_overflow"
Android:orderInCategory="101"
Android:showAsAction="always">
<menu>
<item
Android:id="@+id/action_show_ir_list"
Android:icon="@drawable/ic_menu_friendslist"
Android:showAsAction="always|withText"
Android:title="List"/>
</menu>
</item>
以前の回答に基づいてこれを試してみましたが、少なくとも最新バージョンのサポートライブラリ(25.1)では正常に機能します。
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
if(menu instanceof MenuBuilder){
MenuBuilder m = (MenuBuilder) menu;
//noinspection RestrictedApi
m.setOptionalIconsVisible(true);
}
return true;
}
SpannableStringを使用できます
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_tab, menu);
MenuItem item = menu.findItem(R.id.action_login);
SpannableStringBuilder builder = new SpannableStringBuilder("* Login");
// replace "*" with icon
builder.setSpan(new ImageSpan(this, R.drawable.login_icon), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
item.setTitle(builder);
}
サイモンからの答えは私にとって非常に有用だったので、提案されたonCreateOptionsMenu
- methodへの実装方法を共有したいと思います。
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_action_bar, menu);
// To show icons in the actionbar's overflow menu:
// http://stackoverflow.com/questions/18374183/how-to-show-icons-in-overflow-menu-in-actionbar
//if(featureId == Window.FEATURE_ACTION_BAR && menu != null){
if(menu.getClass().getSimpleName().equals("MenuBuilder")){
try{
Method m = menu.getClass().getDeclaredMethod(
"setOptionalIconsVisible", Boolean.TYPE);
m.setAccessible(true);
m.invoke(menu, true);
}
catch(NoSuchMethodException e){
Log.e(TAG, "onMenuOpened", e);
}
catch(Exception e){
throw new RuntimeException(e);
}
}
//}
return super.onCreateOptionsMenu(menu);
}
上記 からの@Desmond Luaの答えに基づいて、ドロップダウンでXMLで宣言されたドロウアブルを使用する静的メソッドを作成し、色が一定のドローアブル状態に影響しないことを確認しました。
/**
* Updates a menu item in the dropdown to show it's icon that was declared in XML.
*
* @param item
* the item to update
* @param color
* the color to tint with
*/
private static void updateMenuWithIcon(@NonNull final MenuItem item, final int color) {
SpannableStringBuilder builder = new SpannableStringBuilder()
.append("*") // the * will be replaced with the icon via ImageSpan
.append(" ") // This extra space acts as padding. Adjust as you wish
.append(item.getTitle());
// Retrieve the icon that was declared in XML and assigned during inflation
if (item.getIcon() != null && item.getIcon().getConstantState() != null) {
Drawable drawable = item.getIcon().getConstantState().newDrawable();
// Mutate this drawable so the tint only applies here
drawable.mutate().setTint(color);
// Needs bounds, or else it won't show up (doesn't know how big to be)
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
ImageSpan imageSpan = new ImageSpan(drawable);
builder.setSpan(imageSpan, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
item.setTitle(builder);
}
}
そして、アクティビティで使用する場合、これを使用すると次のようになります。これはおそらく、個々のニーズに応じてさらにエレガントになる可能性があります。
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_activity_provider_connect, menu);
int color = ContextCompat.getColor(this, R.color.accent_dark_grey);
updateMenuWithIcon(menu.findItem(R.id.email), color);
updateMenuWithIcon(menu.findItem(R.id.sms), color);
updateMenuWithIcon(menu.findItem(R.id.call), color);
return true;
}
@Simonの答えは本当にうまくいきます...しかし、あなたはAppCompatアクティビティを使用しています...代わりにこのコードを使用する必要があります... onMenuOpened()はappcompat-v7:22.xではもう呼び出されないためです
@Override
protected boolean onPrepareOptionsPanel(View view, Menu menu) {
if(menu != null){
if(menu.getClass().getSimpleName().equals("MenuBuilder")){
try{
Method m = menu.getClass().getDeclaredMethod(
"setOptionalIconsVisible", Boolean.TYPE);
m.setAccessible(true);
m.invoke(menu, true);
}
catch(NoSuchMethodException e){
Log.e(Constants.DEBUG_LOG, "onMenuOpened", e);
}
catch(Exception e){
throw new RuntimeException(e);
}
}
}
return super.onPrepareOptionsPanel(view, menu);
}
現在のところ最高ですが、受け入れられません ソリューション はおそらく古いプラットフォームで動作します。とにかく新しいAppCompat21 +では、必要なメソッドが存在せず、メソッドgetDeclaredMethod
は例外NoSuchMethodException
を返します。
そのため、回避策(テスト済みで4.x、5.xデバイスで動作)は、直接変更のバックグラウンドパラメーターに基づいています。したがって、このコードをActivityクラスに配置するだけです。
@Override
public boolean onMenuOpened(int featureId, Menu menu) {
// enable visible icons in action bar
if (featureId == Window.FEATURE_ACTION_BAR && menu != null) {
if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
try {
Field field = menu.getClass().
getDeclaredField("mOptionalIconsVisible");
field.setAccessible(true);
field.setBoolean(menu, true);
} catch (IllegalAccessException | NoSuchFieldException e) {
Logger.w(TAG, "onMenuOpened(" + featureId + ", " + menu + ")", e);
}
}
}
return super.onMenuOpened(featureId, menu);
}
私が見つけた最も簡単な方法はこれです:
public boolean onCreateOptionsMenu(Menu menu){
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.toolbar_menu,menu);
if(menu instanceof MenuBuilder) { //To display icon on overflow menu
MenuBuilder m = (MenuBuilder) menu;
m.setOptionalIconsVisible(true);
}
return true;
} `
私によると、これはカスタムツールバーを作成することによってのみ可能です。デフォルトのActionBarではその機能が提供されないためです。ただし、サブメニューをアイテムの子として使用してアイコンを配置できます。そして、あなたが私よりも良い解決策を持っているなら..私に知らせてください。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto">
<item
Android:id="@+id/action_settings"
Android:icon="@drawable/ic_menu_camera"
Android:showAsAction="never"
Android:title="@string/action_settings" />
<item
Android:id="@+id/action_1"
Android:icon="@drawable/ic_menu_gallery"
Android:showAsAction="never"
Android:title="Hello" />
<item
Android:id="@+id/action_search"
Android:icon="@Android:drawable/ic_search_category_default"
Android:showAsAction="never"
Android:title="action_search">
<menu>
<item
Android:id="@+id/version1"
Android:icon="@Android:drawable/ic_dialog_alert"
Android:showAsAction="never"
Android:title="Cup cake" />
<item
Android:id="@+id/version2"
Android:icon="@drawable/ic_menu_camera"
Android:showAsAction="never"
Android:title="Donut" />
<item
Android:id="@+id/version3"
Android:icon="@drawable/ic_menu_send"
Android:showAsAction="never"
Android:title="Eclair" />
<item
Android:id="@+id/version4"
Android:icon="@drawable/ic_menu_gallery"
Android:showAsAction="never"
Android:title="Froyo" />
</menu>
</item>
</menu>
ActionModeで使用するSimonの優れたソリューションに対する私の簡単なmod:
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
if(menu != null){
if(menu.getClass().getSimpleName().equals("MenuBuilder")){
try{
Method m = menu.getClass().getDeclaredMethod(
"setOptionalIconsVisible", Boolean.TYPE);
m.setAccessible(true);
m.invoke(menu, true);
}
catch(NoSuchMethodException e){
Log.e(TAG, "onPrepareActionMode", e);
}
catch(Exception e){
throw new RuntimeException(e);
}
}
}
return true;
}
これは遅すぎますが、誰かが_menu.xml
_を使用している人に役立つ@Desmond Luaの回答から助けを得たかもしれません
私の答えは、動的なメニュー作成のためのコードです:
_ int ACTION_MENU_ID =1;
SpannableStringBuilder builder;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//this space for icon
builder = new SpannableStringBuilder(" " + getString(R.string.your_menu_title));
builder.setSpan(new ImageSpan(this, R.drawable.ic_your_menu_icon), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//dynamic menu added
menu.add(Menu.NONE,ACTION_MENU_ID, Menu.NONE,
getString(R.string.your_menu_title))
.setShowAsAction(MenuItemCompat.SHOW_AS_ACTION_WITH_TEXT | MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
//set icon in overflow menu
menu.findItem(ACTION_MENU_ID).setTitle(builder);
}
_
これをスタイルで追加します。
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item
Android:id="@+id/action_settings"
app:showAsAction="always"
Android:icon="@drawable/ic_more_vert_white"
Android:orderInCategory="100"
Android:title="">
<menu>
<item
Android:id="@+id/Login"
Android:icon="@drawable/ic_menu_user_icon"
Android:showAsAction="collapseActionView|withText"
Android:title="@string/str_Login" />
<item
Android:id="@+id/str_WishList"
Android:icon="@drawable/ic_menu_wish_list_icon"
Android:showAsAction="collapseActionView"
Android:title="@string/str_WishList" />
<item
Android:id="@+id/TrackOrder"
Android:icon="@drawable/ic_menu_my_order_icon"
Android:showAsAction="collapseActionView"
Android:title="@string/str_TrackOrder" />
<item
Android:id="@+id/Ratetheapp"
Android:icon="@drawable/ic_menu_rate_the_apps"
Android:showAsAction="collapseActionView"
Android:title="@string/str_Ratetheapp" />
<item
Android:id="@+id/Sharetheapp"
Android:icon="@drawable/ic_menu_shar_the_apps"
Android:showAsAction="collapseActionView"
Android:title="@string/str_Sharetheapp" />
<item
Android:id="@+id/Contactus"
Android:icon="@drawable/ic_menu_contact"
Android:showAsAction="collapseActionView"
Android:title="@string/str_Contactus" />
<item
Android:id="@+id/Policies"
Android:icon="@drawable/ic_menu_policy_icon"
Android:showAsAction="collapseActionView"
Android:title="@string/str_Policies" />
</menu>
</item>
</menu>
public void showContextMenuIconVisible(Menu menu){
if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
try {
Field field = menu.getClass().getDeclaredField("mOptionalIconsVisible");
field.setAccessible(true);
field.setBoolean(menu, true);
} catch (Exception ignored) {
ignored.printStackTrace();
}
}
}