Android Menu的基本使用

在Android中,菜单项是比较常见的一种人机交互方式,通过设置菜单项,既可以节省布局控件,也可以实现更加人性化的操作(可以提供一种不断发掘探索的精神)。其实,关于菜单项,大家都已经见怪不怪了,在windows或者其他操作系统中,已经熟悉的不能再熟悉了,在Android中应用也是非常,例如QQ、微信等都有不少菜单。接下来,简单介绍一下菜单的基本使用。

1.创建选项菜单(Options Menu)

由官方API可知,,onCreateOptionsMenu方法有唯一的一个参数Menu,而通过Menu.add方法可以添加菜单项,从add的重载方法看,最长的含有4个参数(int groupId, int itemId,int order,CharSequence title),其中第一个参数表示菜单项的分组ID,用于带选项按钮的菜单,一般这个参数不需要特别设置,任何整数均可以,而且在测试过程中,发现这个参数引起的变化不明显。第二个参数是当前菜单项ID,相当于一个“身份证”,这个是比较重要的,可以通过这个ID来确认选择的是哪个menu。第三个参数是显示顺序,这个order和menu.xml文件中<item>中的order是一样的,其顺序为从左到右,从上到下。最后一个参数则是该menu的标题。同时要注意,Android中的menu最多可以显示6个,还有多余的则以more的形式显示。

简单的代码示例:

public boolean onCreateOptionsMenu(Menu menu) {
      menu.add(1,1,2,"one");
      menu.add(1,1,2,"two");
      return true;
}
2.带图像的menu

实现的menu带图像很简单,只需要使用setIcon方法就可以,但是在测试过程中发现即使加了这句语言,也不能实现menu带图像,跟度娘请教后才发现,还有个反射函数,才能将图像显示,这里直接把反射函数截取下来:

public boolean onPrepareOptionsMenu(Menu menu) {
     if (menu != null) {
            if (menu.getClass() == MenuBuilder.class) {
                try {
                    Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
                    m.setAccessible(true);
                    m.invoke(menu, true);
                } catch (Exception e) {
            }
         }
     }
     return super.onPrepareOptionsMenu(menu);
}
3.menu点击事件监听

在开发中,menu常常是用来设置参数或者切换Activity来实现扩展功能的,因此menu的事件监听就比较重要,menu的监听方法有三种,最常用的是onOptionsItemSelected和onMenuItemClick这两种方法,第三种onMenuItemSelected方法其实是调用onOptionsItemSelected方法来实现的,这几种方法的使用也很简单。

3.1onOptionsItemSelected

public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_0:

                break;
            case R.id.action_1:

                break;
            case R.id.action_2:

                break;
            case R.id.action_3:

                break;
            default:
                break;
        }
        return super.onOptionsItemSelected(item);
    }
3.2onMenuItemClick

public boolean onMenuItemClick(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_0:

                break;
            case R.id.action_1:

                break;
            case R.id.action_2:

                break;
            case R.id.action_3:

                break;
            default:
                break;
        }
        return false;
    }
4.带复选框的menu

带复选框的menu,需要用到addSubMenu方法,而这个方法返回值为一个Submenu,但是addSubMenu和add方法在使用上完全一致,通过查阅API可以清楚的看到,SubMenu也可以直接设置menu图像,同时还有两个方法setCheckable和setChecked,这两个方法的参数均是boolean类型的参数,前者表示是否将该menu设置为复选框形式,后者表示是否选中,那么如果想要将父菜单下的子菜单设置成复选框类型,是否需要将每一个子菜单设置setChecked方法呢?答案呢当然是否,前文提到的menu.add参数的第一个参数是groupId,代表组别,那么只需要将这些子菜单设置成同样的groupId,使用setGroupCheckable来设置这个groupId,第二个参数必须设置为true,而第三个参数为true,则代表设置为选项按钮效果,false带白哦设置成复选框效果。

public boolean onCreateOptionsMenu(Menu menu) {
        SubMenu fileSubMenu = menu.addSubMenu(1,1,2,"文件");
        fileSubMenu.setIcon(R.drawable.little_animal_02);
        fileSubMenu.setHeaderIcon(R.drawable.little_animal_06);
        MenuItem menuItem = fileSubMenu.add(1,2,2,"新建");
        menuItem.setCheckable(true);
        menuItem.setChecked(true);
        MenuItem openMenuItem = fileSubMenu.add(2,3,3,"打开");
        MenuItem exitMenuItem = fileSubMenu.add(2,4,4,"退出");
        exitMenuItem.setChecked(true);
        fileSubMenu.setGroupCheckable(2,true,true);
        return true;
    }
5.具有上一节title的menu

具有的上一级title的menu,又叫上下文菜单,效果就是当你电机一个menu,出现该menu的子菜单选项,这个时候在这些菜单选项的上边儿会出现父菜单的标题。

效果如下:


实现起来也很简单,需要覆盖onCreateContextMenu方法,代码如下:

public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        menu.setHeaderTitle("上下文菜单");
        menu.setHeaderIcon(R.drawable.little_animal_10);
        //添加3个上下文菜单项,Menu.NONE的值是0
        menu.add(0,menuItemId++,Menu.NONE,"菜单1").setCheckable(true).setChecked(true);
        menu.add(20,menuItemId++,Menu.NONE,"菜单2");
        //选中第二个选项按钮
        menu.add(20,menuItemId++,Menu.NONE,"菜单3").setChecked(true);
        menu.setGroupCheckable(20,true,true);
        //添加袋子菜单的上下文菜单项
        SubMenu sub = menu.addSubMenu(0,menuItemId++,Menu.NONE,"子菜单");
        sub.add("子菜单1");
        sub.add("子菜单2");

}
其中add方法中的参数和之前介绍的参数一致。

7.介绍完上述的常用的几种菜单,接下来介绍一些在使用过程中遇到的问题。

7.1menu的位置,我们在设置完一个menu时,点击会发现,menu会覆盖标题栏,这样会使得用户体验很差很差,而且也不美观,那么如何让menu下移,不覆盖标题栏呢?

通过摸索和查阅,发现是否覆盖标题栏涉及到主题的问题,需要在自定义一个主题,设置overlapAnchor为false,同时将该主题应用到AppTheme中,其实,通过自定义menu主题,我们可以自定义设置很多东西,例如menu背景颜色,menu和title的距离等。

具体的代码如下:

    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="android:overlapAnchor">false</item>
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <!--menu主题-->
        <item name="actionOverflowMenuStyle">@style/LYJMenuStyle</item>

    </style>

    <style name="LYJMenuStyle" parent="@style/Widget.AppCompat.Light.PopupMenu.Overflow">
        <!--是否覆盖Title-->
        <item name="overlapAnchor">false</item>
        <!--背景颜色-->
        <item name="android:popupBackground">@color/White</item>
        <!--menu与Title的距离-->
        <item name="android:dropDownVerticalOffset">5dp</item>
    </style>
7.2通过menu.xml文件来设置menu

Android studio中很人性化的提供了这一方法,通过这一方法,我们可以很简单的设置menu,而不需要通过前面的大量的代码来手动添加menu(包括上下文菜单等),解决的很多问题,那么在创建好menu.xml文件后,该如何显示到主UI中呢,这就需要在onCreateOptionsMenu中装载此文件,通过getMenuInflater.inflate(R.menu.menu,null)方法来装载该mennu文件,参数为该menu文件ID。关于menu.xml文件的创建,需要在res文件夹下创建一个menu文件夹。下面的示例创建了一个上下文菜单。

    <item
        android:id="@+id/action_settings"
        android:orderInCategory="100"
        android:title="@string/action_settings"
        app:showAsAction="never"/>
    <item android:id="@+id/mode_select"
        android:title="模式选择"
        android:orderInCategory="100">
        <menu>
            <item android:id="@+id/manual_mode"
                android:orderInCategory="100"
                android:title="手动模式"/>
                <!--app:showAsAction="never"/>-->
            <item android:id="@+id/automatic_mode"
                android:orderInCategory="100"
                android:title="自动模式"/>
                <!--app:showAsAction="never"/>-->
        </menu>
    </item>
第二个<item>中又添加了两个menu,这样就可以实现上下文菜单,比起纯代码的书写来是不是很方便。

7.3再来介绍一下,如何设置手机的“menu”键和软件的menu键的关联

在使用手机的过程中,我们经常会发现,点击手机的硬触控也会触发软件的menu,比如很早之前的浏览器,那么这种功能是如何实现的呢?记得在之前,我写过一个关于如何实现自拍杆功能的博文,当时是为了自定义开发一个相机而实现自拍杆功能,那篇文章介绍了Android的中的一个比较强大的onKeyDown方法,可以用来实现手机的一些硬触发按键的监听功能,那么,实现menu的关联,也可以通过此方法。具体代码如下:

/**
     * 点击手机上的menu键Ω
     * */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch (keyCode){
            case KeyEvent.KEYCODE_MENU://按下"menu"键动作
                //选项菜单已弹出,不再弹出新的窗口
                if (state == 1)
                    return false;
                //装载选项菜单布局
                layout = getLayoutInflater().inflate(R.layout.menu_layout,null);
                //创建PopupWindows对象,并在指定位置弹出用于显示菜单的窗口
                pop = new PopupWindow(layout,getWindowManager().getDefaultDisplay().getWidth(),
                        getWindowManager().getDefaultDisplay().getHeight());
                //设置弹出窗口的置
                pop.showAtLocation(layout, Gravity.BOTTOM,0,0);
                View home = layout.findViewById(R.id.home);
                //为"首页"菜单添加单击事件
                home.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(MainActivity.this, "单击定制菜单", Toast.LENGTH_SHORT).show();
                        //单击"首页"菜单项后,关闭选项菜单
                        pop.dismiss();
                        state = 2;
                    }
                });
                //弹出选项菜单后,将状态变量设为1,表示选项菜单已弹出
                state = 1;
                break;
            case KeyEvent.KEYCODE_BACK:
                if (state == 1){
                    //如果选项菜单已弹出,关闭它
                    pop.dismiss();
                    //将状态变量设为选项菜单已关闭
                    state = 2;
                }else if (state == 2){
                    //如果选项菜单还没有显示,或已经关闭,则直接关闭当前activity
                    finish();
                }
                break;
        }
        //除"menu"和"back"按下事件,仍需调用activity类的onKeyDown方法来响应其他按键的按下事件
        return super.onKeyDown(keyCode,event);
    }

——参考自《Android开发权威指南》






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值