在工具栏溢出菜单中显示菜单项图标时,这种奇怪的情况是如何发生的?
How does this strange condition happens when show menu item icon in toolbar overflow menu?
我想在工具栏中显示一个溢出菜单(AppCompat-v7:22.1.1),下面是我的menu_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/action_search"
android:title="@string/action_search"
android:icon="@mipmap/ic_menu_search"
android:orderInCategory="100"
android:actionViewClass="android.widget.SearchView"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/menu_group_chat"
android:title="@string/menu_group_chat"
android:icon="@mipmap/ic_menu_groupchat" />
<item
android:id="@+id/menu_add_friend"
android:title="@string/menu_add_friend"
android:icon="@mipmap/ic_menu_add_friend" />
我的应用程序运行后,菜单项的图标不显示,然后我尝试了这个solution,在我的Activty中添加了一个覆盖方法onMenuOpened()
(扩展自AppCompatActivity
),
@Override
public boolean onMenuOpened(int featureId, 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 (Exception e) {
e.printStackTrace();
}
}
}
return super.onMenuOpened(featureId, menu);
}
但是运行这个demo之后,我发现图标还是没有显示
从这个reported issue,我知道在22.x中不再调用AppCompatActivity.onMenuOpened
,但奇怪的是当我在Genymotion中点击硬件菜单键时,菜单出现在底部并带有图标,
关闭菜单后,我再次点击工具栏中的溢出按钮,出现菜单中的这些图标,
好奇怪啊!为什么会这样?
对于 AppCompactActivity,您可以将此检查放在 onPrepareOptionsPanel() 上。
@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 (Exception e) {
Log.e(getClass().getSimpleName(), "onMenuOpened...unable to set icons for overflow menu", e);
}
}
}
return super.onPrepareOptionsPanel(view, menu);
}
这里是对 Alécio Carvalho 上面提供的优秀答案的修改。如果需要正确显示图标而不是在主应用程序的操作栏中,而是在每个单独片段中的 自定义工具栏 中(我想要一个单独的工具栏,带有自己的标题和为每个片段自定义操作菜单,而不是简单地向整个 AppCompatActivity 的操作栏添加新项目。
对于上述情况,片段 class 如下:
public class MyFragment extends android.support.v4.app.Fragment {
...
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//at first get the very toolbar
fragmentToolbar = (Toolbar) view.findViewById(R.id.fragment_toolbar);
fragmentToolbar.setTitle(R.string.title_string);
fragmentToolbar.showOverflowMenu();
//now ready to get the menu's method, which is responsible for icons, and change its properties
Menu menu=fragmentToolbar.getMenu();
Method menuMethod = null;
try {
menuMethod = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
menuMethod.setAccessible(true);
menuMethod.invoke(menu, true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
//now all the other stuff necessary for the toolbar operation
fragmentToolbar.inflateMenu(R.menu.my_fragment_menu);
fragmentToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem arg0) {
if(arg0.getItemId() == R.id.menu_item_1){
...
}
return false;
}
});
//and now the main stuff of onCreateView
View view = inflater.inflate(R.layout.my_fragment_layout, container, false);
return view;
}
}
然后my_fragment_layout.xml包含菜单如下
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:id="@+id/fragment_toolbar"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:elevation="4dp">
</android.support.v7.widget.Toolbar>
//...other items
</LinearLayout>
一个典型的菜单文件实现为 res/menu/my_fragment_menu.xml
。
该片段被简单地添加到 mainActivity 的布局中
<fragment android:id="@+id/my_fragment_id"
android:name="com.appspot.trendy.trendychart.MyFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
@SuppressLint("RestrictedApi")
public void initToolBar(){
MenuBuilder menuBuilder = (MenuBuilder) toolbar.getMenu();
menuBuilder.setOptionalIconsVisible(true);
}
我是这样解决的
这对我有用
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.my_menu, menu);
//this section is the one that allows to visualize the icon
if(menu instanceof MenuBuilder){
MenuBuilder m = (MenuBuilder) menu;
//noinspection RestrictedApi
m.setOptionalIconsVisible(true);
}
return true;
}
我想在工具栏中显示一个溢出菜单(AppCompat-v7:22.1.1),下面是我的menu_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/action_search"
android:title="@string/action_search"
android:icon="@mipmap/ic_menu_search"
android:orderInCategory="100"
android:actionViewClass="android.widget.SearchView"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/menu_group_chat"
android:title="@string/menu_group_chat"
android:icon="@mipmap/ic_menu_groupchat" />
<item
android:id="@+id/menu_add_friend"
android:title="@string/menu_add_friend"
android:icon="@mipmap/ic_menu_add_friend" />
我的应用程序运行后,菜单项的图标不显示,然后我尝试了这个solution,在我的Activty中添加了一个覆盖方法onMenuOpened()
(扩展自AppCompatActivity
),
@Override
public boolean onMenuOpened(int featureId, 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 (Exception e) {
e.printStackTrace();
}
}
}
return super.onMenuOpened(featureId, menu);
}
但是运行这个demo之后,我发现图标还是没有显示
从这个reported issue,我知道在22.x中不再调用AppCompatActivity.onMenuOpened
,但奇怪的是当我在Genymotion中点击硬件菜单键时,菜单出现在底部并带有图标,
关闭菜单后,我再次点击工具栏中的溢出按钮,出现菜单中的这些图标,
好奇怪啊!为什么会这样?
对于 AppCompactActivity,您可以将此检查放在 onPrepareOptionsPanel() 上。
@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 (Exception e) {
Log.e(getClass().getSimpleName(), "onMenuOpened...unable to set icons for overflow menu", e);
}
}
}
return super.onPrepareOptionsPanel(view, menu);
}
这里是对 Alécio Carvalho 上面提供的优秀答案的修改。如果需要正确显示图标而不是在主应用程序的操作栏中,而是在每个单独片段中的 自定义工具栏 中(我想要一个单独的工具栏,带有自己的标题和为每个片段自定义操作菜单,而不是简单地向整个 AppCompatActivity 的操作栏添加新项目。
对于上述情况,片段 class 如下:
public class MyFragment extends android.support.v4.app.Fragment {
...
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//at first get the very toolbar
fragmentToolbar = (Toolbar) view.findViewById(R.id.fragment_toolbar);
fragmentToolbar.setTitle(R.string.title_string);
fragmentToolbar.showOverflowMenu();
//now ready to get the menu's method, which is responsible for icons, and change its properties
Menu menu=fragmentToolbar.getMenu();
Method menuMethod = null;
try {
menuMethod = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
menuMethod.setAccessible(true);
menuMethod.invoke(menu, true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
//now all the other stuff necessary for the toolbar operation
fragmentToolbar.inflateMenu(R.menu.my_fragment_menu);
fragmentToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem arg0) {
if(arg0.getItemId() == R.id.menu_item_1){
...
}
return false;
}
});
//and now the main stuff of onCreateView
View view = inflater.inflate(R.layout.my_fragment_layout, container, false);
return view;
}
}
然后my_fragment_layout.xml包含菜单如下
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:id="@+id/fragment_toolbar"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:elevation="4dp">
</android.support.v7.widget.Toolbar>
//...other items
</LinearLayout>
一个典型的菜单文件实现为 res/menu/my_fragment_menu.xml
。
该片段被简单地添加到 mainActivity 的布局中
<fragment android:id="@+id/my_fragment_id"
android:name="com.appspot.trendy.trendychart.MyFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
@SuppressLint("RestrictedApi")
public void initToolBar(){
MenuBuilder menuBuilder = (MenuBuilder) toolbar.getMenu();
menuBuilder.setOptionalIconsVisible(true);
}
我是这样解决的
这对我有用
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.my_menu, menu);
//this section is the one that allows to visualize the icon
if(menu instanceof MenuBuilder){
MenuBuilder m = (MenuBuilder) menu;
//noinspection RestrictedApi
m.setOptionalIconsVisible(true);
}
return true;
}