Android Menu的基本使用

来源:互联网 发布:球球大作战挂机软件 编辑:程序博客网 时间:2024/06/06 03:36

在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
原创粉丝点击