文章目录
- 介绍
 - 简单使用
 
- 通过xml创建选项菜单
 - 动态添加菜单
 
- 配置子菜单
 
- 通过xml添加子菜单
 - 动态添加子菜单
 
- 显示图标
 - Fragment中使用OptionsMenu
 - 实现右上角更多显示菜单
 - OptionMenu弹出位置
 
介绍
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 {
    
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_menu);
    }
    
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    
    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
 
<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;
    
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_menu);
    }
    
    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;
    }
    
    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菜单文件
 
<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;
    
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_menu);
    }
    
    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;
    }
    
    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
 
<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>程序中重写以下方法
    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 {
        
        public void onCreate(Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            super.onCreate(savedInstanceState);
            setHasOptionsMenu(true);
        }
}重写以下方法
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.menu_message_option,menu);
    }
    
    
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case R.id.xx:
                //点击菜单的操作
                break;
        }
        return super.onOptionsItemSelected(item);
    }实现右上角更多显示菜单

 
<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>参考
ActionBar中OptionMenu弹出菜单的位置和overflow右边距的调整










