Android Studio 之 菜单 Menu

选项菜单 OptionsMenu

用xml添加(更建议使用)

创建一个菜单布局 :

  • 在 res文件下新建一个menu 目录,此时的菜单id为:R.menu.option

<?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">
    <!-- 菜单可以嵌套 但顶多允许含有一层子菜单-->
    <!--
        showAsAction:always 直接在标题栏显示 never 不显示 有图标就显示图标
    -->
    <item
        android:id="@+id/m1"
        android:title="选项1"
        app:showAsAction="always"/>
    <item
        android:id="@+id/m2"
        android:title="选项2"/>
    <item
        android:id="@+id/m3"
        android:title="选项3"/>
    <item
        android:id="@+id/m4"
        android:title="选项4">
        <menu>
            <item android:title="子菜单1"/>
            <item android:title="子菜单2"/>
            <item android:title="子菜单3"/>
            <item android:title="子菜单4"/>
        </menu>
    </item>

</menu>

在需要添加选项菜单的布局对应的activity中创建选项菜单-此时是MainActivity

getMenuInflater().inflate(R.menu.option,menu); // 加载菜单资源
// 创建optionMenu
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // 加载菜单资源
        getMenuInflater().inflate(R.menu.option,menu);
        return true;
    }

    // optionMenu 的选中方法
    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        if (item.getItemId() == R.id.m1) {
            Toast.makeText(this,item.getTitle(),Toast.LENGTH_SHORT).show();
        } else if (item.getItemId() == R.id.m2) {
            Toast.makeText(this,item.getTitle(),Toast.LENGTH_SHORT).show();
        }
        return super.onOptionsItemSelected(item);
    }

使用Java添加

  • Menu 类 SubMenu 子菜单类
  • Menu类参数:组id 菜单项id 菜单项序号 菜单项名称

在onCreateOptionsMenu 方法里利用以上类添加选项菜单,菜单项序号是指菜单项的位置

// 创建optionMenu
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // 加载菜单资源
        /* 通过xml设计 */
        // getMenuInflater().inflate(R.menu.option,menu);
        /* 纯代码设计
         * Menu 类 SubMenu 子菜单类*/
        /* Menu 类参数:组id 菜单项 id 菜单项序号 菜单项名称 */
        menu.add(1,1,3,"菜单1");
        menu.add(1,2,2,"菜单2");
        SubMenu subMenu = menu.addSubMenu(1,3,1,"子菜单的主菜单");
        subMenu.add(2,22,1,"子菜单2");
        subMenu.add(2,11,2,"子菜单1");
        return true;
    }

上下文菜单 ContextMenu

长按按钮弹出菜单

创建菜单布局

  • 在 res文件下新建一个menu 目录,此时的菜单id为:R.menu.context
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/ctx1"
        android:title="上下文菜单item1" />
    <item
        android:id="@+id/ctx2"
        android:title="上下文菜单item2" />
    <item
        android:id="@+id/ctx3"
        android:title="上下文菜单item3" />
    <item
        android:id="@+id/ctx4"
        android:title="上下文菜单item4" />
    <item
        android:title="上下文菜单item5">
        <menu>
            <item
                android:id="@+id/z_ctx1"
                android:title="子菜单item1" />
            <item
                android:id="@+id/z_ctx2"
                android:title="子菜单item2" />
            <item
                android:id="@+id/z_ctx3"
                android:title="子菜单item3" />
        </menu>
    </item>
</menu>

创建菜单

在activity_main.xml里添加一个按钮用以打开上下文菜单

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:gravity="center"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/ctx_btn"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="打开contextMenu"/>

</LinearLayout>

 上下文菜单的使用步骤:

1.注册

在 activity_main.xml 布局对应的 activity 中的 onCreate() 方法中进行注册

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // ContextMenu 上下文菜单的使用
        // 1.注册
        registerForContextMenu(findViewById(R.id.ctx_btn));
 }

2.创建 - 覆盖父类的 onCreateContextMenu 方法

// 2.创建contextMenu
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        getMenuInflater().inflate(R.menu.context,menu);
    }

3菜单项的操作 - 覆盖父类的 onContextItemSelected 方法

// 3.contextMenu 菜单项选项操作
    @Override
    public boolean onContextItemSelected(@NonNull MenuItem item) {

        int itemId = item.getItemId();
        Toast.makeText(this, item.getTitle(), Toast.LENGTH_SHORT).show();
        return super.onContextItemSelected(item);
    }

上下文菜单 - 上下文操作模式 

 菜单会出现在状态栏的位置

1. 实现接口 ActonMode.CallBack 中不同的回调方法

ActionMode.Callback ac =new ActionMode.Callback(){
        // 创建:在启动上下文操作模式(startActionMode(Callback))时调用
       @Override
       public boolean onCreateActionMode(ActionMode mode, Menu menu) {
           Log.e("上下文操作模式","--创建--");
           getMenuInflater().inflate(R.menu.context,menu);
           return true;
       }

       // 准备:在创建方法后进行调用
       @Override
       public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
           Log.e("上下文操作模式","--准备--");
           return false;
       }

       // 菜单项被点击
       @Override
       public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
           /* 环境变量此时需要这样是因为这是一个内部类 ButtonActivity.this */
           Log.e("上下文操作模式","--点击--");
           Toast.makeText(ButtonActivity.this, item.getTitle(), Toast.LENGTH_SHORT).show();
           return true;
       }

       // 结束:上下文操作模式结束时调用
       @Override
       public void onDestroyActionMode(ActionMode mode) {
           Log.e("上下文操作模式","--结束--");
       }
   };

2. 添加一个按钮用以打开,上下文操作模式

<Button
        android:id="@+id/ctx_opbtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="上下文 ContextMenu 操作模式"/>

3.在View的长按事件中启动上下文操作模式 

findViewById(R.id.ctx_opbtn).setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                startActionMode(ac);
                return false;
            }
        });

弹出式菜单

一般出现在被绑定的View下方,如果下方没有空间则出现在上方

添加一个按钮

 <Button
        android:id="@+id/pop_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="弹出式菜单"/>

为这个按钮添加点击事件,并将弹出式菜单绑定在按钮的点击事件上 

// 将弹出式菜单绑定在按钮的点击事件上
        Button popbtn = findViewById(R.id.pop_btn);
        popbtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 1.实例化 PopupMenu 对象
                /* 参数一 上下文环境
                 * 参数二 被锚定的(绑定)的button*/
                PopupMenu popupMenu = new PopupMenu(ButtonActivity.this,popbtn);
                // 2.加载菜单资源:利用MenuInflater将Menu资源加载到PopMenu.getMenu() 所返回的Menu对象中
                popupMenu.getMenuInflater().inflate(R.menu.context,popupMenu.getMenu());
                // 3.菜单子项点击操作
                popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                    @Override
                    public boolean onMenuItemClick(MenuItem item) {
                        Toast.makeText(ButtonActivity.this, item.getTitle(), Toast.LENGTH_SHORT).show();
                        return false;
                    }
                });
                // 显示菜单
                popupMenu.show();
            }
        });