文章目录
介绍
OptionMenu 选项菜单,是通过点击设备上的 Menu 键弹出的菜单
【配置菜单】
加载 OptionMenu 是通过执行 Activity 中的 onCreateOptionMenu()
方法来实现的。
1、通过配置 res/menu/ 下的菜单配置文件,可以设置菜单项,每个菜单项中:android:id
属性是其唯一标识,亦用于响应点击菜单项时的匹配;android:orderInCategory
属性表示菜单项的排序,由小到大排序,如果数字相同,按照代码先后顺序显示;
android:showAsAction
属性可以无视;
android:title
属性表示菜单项显示的文字;
android:icon
属性可以为菜单项配置小图标
2、可以通过在 onCreateOptionMenu()
方法中调用参数 Menu 对象的 add()
方法动态的添加菜单项
【响应菜单项的点击】
通过重写 onOptionItemSelected()
方法可以实现对菜单项的选择的响应
简单使用
通过xml创建选项菜单
MenuActivity
public class MenuActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_file:
Toast.makeText(this, "点击了File", Toast.LENGTH_SHORT).show();
break;
case R.id.action_edit:
Toast.makeText(this, "点击了Edit", Toast.LENGTH_SHORT).show();
break;
case R.id.action_view:
Toast.makeText(this, "点击了View", Toast.LENGTH_SHORT).show();
break;
}
return super.onOptionsItemSelected(item);
}
}
在 res 下新建 menu 文件夹,在其中创建 main.xml
<?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_file"
android:orderInCategory="100"
android:title="File"
app:showAsAction="never" />
<item
android:id="@+id/action_edit"
android:orderInCategory="100"
android:title="Edit"
app:showAsAction="never" />
<item
android:id="@+id/action_view"
android:orderInCategory="100"
android:title="View"
app:showAsAction="never" />
</menu>
我们运行到模拟机上,虽然模拟机已经没有了 Menu 键,但可以使用 Ctrl+M 快捷键来实现点击了 Menu 键。Menu 之所以显示在下面是因为 MenuActivity 使用的是 NotitleBar 的主题。
动态添加菜单
menu.add(groupid,itemid,order,title);
groupid
,是分组 id,但是由于安卓中的分组没有明显的效果,这里我们都给 0
itemid
是不能冲突的,因为我们一会儿要通过item.getItemId()
来获得itemid
来进行响应
order
是排序
title
就是最后显示的文字
栗子:通过代码动态添加菜单
public class MenuActivity extends AppCompatActivity {
public static final int MENU_ITEM_NAVIGATE = 1;
public static final int MENU_ITEM_CODE = 2;
public static final int MENU_ITEM_ANALYZE = 3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//getMenuInflater().inflate(R.menu.main,menu);
menu.add(Menu.NONE, MENU_ITEM_NAVIGATE, Menu.NONE, "Navigate");
menu.add(Menu.NONE, MENU_ITEM_CODE, Menu.NONE, "Code");
menu.add(Menu.NONE, MENU_ITEM_ANALYZE, Menu.NONE, "Analyze");
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_ITEM_NAVIGATE:
Toast.makeText(this, "点击了Navigate", Toast.LENGTH_SHORT).show();
break;
case MENU_ITEM_CODE:
Toast.makeText(this, "点击了Code", Toast.LENGTH_SHORT).show();
break;
case MENU_ITEM_ANALYZE:
Toast.makeText(this, "点击了Analyze", Toast.LENGTH_SHORT).show();
break;
}
return super.onOptionsItemSelected(item);
}
}
效果和刚才是相同的
配置子菜单
1、将一级菜单项的节点修改为首位标签对应的格式,如<item></item>
,并在该节点下添加<menu></menu>
子节点,然后在<menu></menu>
子节点中再添加若干个下级的<item>
节点来配置各菜单项
2、将添加一级菜单的add()
方法修改为 addSubMenu()
方法,并获取该方法的返回值,即 SubMenu 类型的对象,然后调用 SubMenu 对象的 add()
方法添加子菜单
通过xml添加子菜单
修改menu菜单文件
<?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_file"
android:orderInCategory="100"
android:title="File"
app:showAsAction="never">
<menu>
<item
android:id="@+id/action_new"
android:orderInCategory="100"
android:title="New"
app:showAsAction="never" />
<item
android:id="@+id/action_open"
android:orderInCategory="100"
android:title="Open"
app:showAsAction="never" />
</menu>
</item>
<item
android:id="@+id/action_edit"
android:orderInCategory="100"
android:title="Edit"
app:showAsAction="never" />
<item
android:id="@+id/action_view"
android:orderInCategory="100"
android:title="View"
app:showAsAction="never" />
</menu>
动态添加子菜单
通过add
添加的菜单是一级菜单,不能拥有子菜单;通过menu.addSubMenu()
添加的菜单能拥有子菜单。
public class MenuActivity extends AppCompatActivity {
public static final int MENU_ITEM_NAVIGATE = 1;
public static final int MENU_ITEM_CODE = 2;
public static final int MENU_ITEM_ANALYZE = 3;
public static final int MENU_ITEM_INSPECT_CODE = 4;
public static final int MENU_ITEM_CODE_CLEANUP = 5;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//getMenuInflater().inflate(R.menu.main,menu);
menu.add(Menu.NONE, MENU_ITEM_NAVIGATE, Menu.NONE, "Navigate");
menu.add(Menu.NONE, MENU_ITEM_CODE, Menu.NONE, "Code");
SubMenu subMenu = menu.addSubMenu(Menu.NONE, MENU_ITEM_ANALYZE, Menu.NONE, "Analyze");
subMenu.add(Menu.NONE, MENU_ITEM_INSPECT_CODE, Menu.NONE, "Inspect Code");
subMenu.add(Menu.NONE, MENU_ITEM_CODE_CLEANUP, Menu.NONE, "Code Cleanup");
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_ITEM_NAVIGATE:
Toast.makeText(this, "点击了Navigate", Toast.LENGTH_SHORT).show();
break;
case MENU_ITEM_CODE:
Toast.makeText(this, "点击了Code", Toast.LENGTH_SHORT).show();
break;
case MENU_ITEM_INSPECT_CODE:
Toast.makeText(this, "点击了Inspect Code", Toast.LENGTH_SHORT).show();
break;
case MENU_ITEM_CODE_CLEANUP:
Toast.makeText(this, "点击了Code Cleanup", Toast.LENGTH_SHORT).show();
break;
}
return super.onOptionsItemSelected(item);
}
}
显示图标
menu
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_file"
android:icon="@drawable/clock"
android:title="定时" />
<item
android:id="@+id/action_view"
android:icon="@drawable/fingerprint"
android:title="指纹" />
</menu>
程序中重写以下方法
@Override
public boolean onPrepareOptionsMenu(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) {
} catch (Exception e) {
}
}
}
return super.onPrepareOptionsMenu(menu);
}
Fragment中使用OptionsMenu
需要在onCreate()
中增加setHasOptionsMenu(true);
,否则菜单不显示
public static class DetailsFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
}
重写以下方法
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_message_option,menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.xx:
//点击菜单的操作
break;
}
return super.onOptionsItemSelected(item);
}
实现右上角更多显示菜单
<?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_file"
android:icon="@mipmap/ic_message_settings"
android:title="更多"
app:showAsAction="always">
<menu>
<item
android:id="@+id/menu_all_read"
android:title="全部已读" />
<item
android:id="@+id/menu_all_clear"
android:title="清空消息" />
</menu>
</item>
</menu>
OptionMenu弹出位置
OptionMenu 的显示以前是显示在 overflow 的下面,5.0 以后显示的位置直接覆盖了 overflow 图标,我们看到上一个栗子中的菜单就是覆盖效果,那么怎么才能实现以下效果呢?
解决办法:
- 在
values-v21 styles.xml
文件中添加
<style name="OverflowMenuStyle" parent="Widget.AppCompat.PopupMenu.Overflow">
<!-- Api 21 -->
<item name="overlapAnchor">false</item>
<!-- 弹出层背景颜色 -->
<item name="android:popupBackground">@color/action_bar_title_text_color</item>
<!-- 设置弹出菜单文字颜色 -->
<item name="android:textColor">@color/message_text</item>
</style>
- 在使用的主题中添加
<item name="actionOverflowMenuStyle">@style/OverflowMenuStyle</item>