Android Menu 添加 Icon 无效问题的解决

Android Menu 添加 Icon 无效问题

问题分析

在 Android4.0 系统中,创建菜单 Menu,通过setIcon 方法给菜单添加图标是无效的,图标没有显出来,但在 Android 2.3 系统中是可以显示出来的。这个问题的根本原因在于 4.0 系统中,涉及到菜单的源码类 MenuBuilder 做了改变,该类的部分源码如下:

public class MenuBuilder implements Menu { ... private boolean mOptionalIconsVisible = false; ... void setOptionalIconsVisible(boolean visible) { mOptionalIconsVisible = visible; } boolean getOptionalIconsVisible() { return mOptionalIconsVisible; } ... } 

上面的代码中,mOptionalIconsVisible 成员初始值默认为 false,这就是为什么给菜单设置图标没有效果的原因

解决思路

所以,只要我们在创建 Menu 时通过调用 setOptionalIconsVisible 方法设置 mOptionalIconsVisible 为 true 就可以了。

难点:要想调用该方法,就需要创建 MenuBuilder对象,但是,我们是无法在开发的应用程序中创建 MenuBuilder 这个对象的 -- MenuBuilder 为系统内部的框架类

这时候就需要考虑用反射了,在代码运行创建菜单的时候通过反射调用 setOptionalIconsVisible方法设置mOptionalIconsVisible 为 true,然后在给菜单添加 Icon,这样就可以在菜单中显示添加的图标了

Java Code:

import java.lang.reflect.Method; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; public class MainActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override public boolean onCreateOptionsMenu(Menu menu) { //运行时,参数Menu其实就是MenuBuilder对象 Log.d("MainActivity", "menu--->" + menu); /*利用反射机制调用MenuBuilder的setOptionalIconsVisible方法设置mOptionalIconsVisible为true, * 给菜单设置图标时才可见 */ setIconEnable(menu, true); MenuItem item1 = menu.add(0, 1, 0, R.string.item1); item1.setIcon(R.drawable.camera); MenuItem item2 = menu.add(0, 1, 0, R.string.item2); item2.setIcon(R.drawable.dial); MenuItem item3 = menu.add(0, 1, 0, R.string.item3); item3.setIcon(R.drawable.sms); return super.onCreateOptionsMenu(menu); } @Override public boolean onPrepareOptionsMenu(Menu menu) { // TODO Auto-generated method stub return super.onPrepareOptionsMenu(menu); } //enable为true时,菜单添加图标有效,enable为false时无效。4.0系统默认无效 private void setIconEnable(Menu menu, boolean enable) { try { Class<?> clazz = Class.forName("com.android.internal.view.menu.MenuBuilder"); Method m = clazz.getDeclaredMethod("setOptionalIconsVisible", boolean.class); m.setAccessible(true); //MenuBuilder实现Menu接口,创建菜单时,传进来的menu其实就是MenuBuilder对象(java的多态特征) m.invoke(menu, enable); } catch (Exception e) { e.printStackTrace(); } } } 

Xamarin.Android Code:

using Android.App;
using Android.Views; using Android.OS; using Android.Support.V7.App; using Android.Widget; using Toolbar = Android.Support.V7.Widget.Toolbar; using Android.Media; using Android.Runtime; namespace HelloToolbar { [Activity(Label = "Support v7 Toolbar", MainLauncher = true, Icon = "@drawable/icon")] public class MainActivity : MyBaseActivity { protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); // Set our view from the "main" layout resource SetContentView(Resource.Layout.main); var toolbar = FindViewById<Toolbar>(Resource.Id.toolbar); //Toolbar will now take on default actionbar characteristics SetSupportActionBar(toolbar); SupportActionBar.Title = "Hello from Appcompat Toolbar"; var toolbarBottom = FindViewById<Toolbar>(Resource.Id.toolbar_bottom); toolbarBottom.Title = "Photo Editing"; toolbarBottom.InflateMenu(Resource.Menu.photo_edit); toolbarBottom.MenuItemClick += (sender, e) => { Toast.MakeText(this, "Bottom toolbar pressed: " + e.Item.TitleFormatted, ToastLength.Short).Show(); }; FindViewById<ImageView>(Resource.Id.image).Click += (sender, e) => { //StartActivity(typeof(CanvasActivity)); }; } /// <Docs>The options menu in which you place your items.</Docs> /// <returns>To be added.</returns> /// <summary> /// This is the menu for the Toolbar/Action Bar to use /// </summary> /// <param name="menu">Menu.</param> public override bool OnCreateOptionsMenu (IMenu menu) { MenuInflater.Inflate (Resource.Menu.home, menu); return base.OnCreateOptionsMenu (menu); } public override bool OnOptionsItemSelected (IMenuItem item) { Toast.MakeText(this, "Top ActionBar pressed: " + item.TitleFormatted, ToastLength.Short).Show(); return base.OnOptionsItemSelected (item); } public override bool OnMenuOpened(int featureId, IMenu menu) { System.Diagnostics.Debug.WriteLine(featureId); if (menu != null) { var javaObj = (Java.Lang.Object)menu; var javaClass = javaObj.Class; if (javaClass.SimpleName.EndsWith("MenuBuilder")) { try { Java.Lang.Reflect.Method m = javaClass.GetDeclaredMethod("setOptionalIconsVisible", new Java.Lang.Class[] { Java.Lang.Boolean.Type }); m.Accessible = true; m.Invoke(javaObj, new Java.Lang.Object[] { true }); } catch (Java.Lang.NoSuchFieldException e) { System.Console.WriteLine("onMenuOpened:{0}", e.ToString()); } } } return base.OnMenuOpened(featureId, menu); } } }

猜你喜欢

转载自www.cnblogs.com/liumin-txgt/p/13161492.html