android之菜单(menu)

江永安
2023-12-01

一 前言

       菜单在桌面应用中使用十分广泛,在android中由于屏幕的限制,android 3.0之后,就不要求android手机上必须MENU键,加上ActionBar的出现,菜单在android手机上使用越来越少,那么为什么还要总结这个东西?本人开始做android项目的时候,也感觉这个东西可有可无(基本上都是自定义标题栏),即使在一些项目中出现过,也没有太关注,但学习android而不去了解它,感觉又少点什么,那就简单地了解下,在这里对之前了解的菜单作下总结,其实菜单中有些东西还是蛮有用的例如弹出菜单,在点击一个View控件时,在该控件上方或者下方弹出一个选择框,这时使用弹出菜单就很方便,不必自己去自定义PopupWindow,还比如,长按一个View控件,弹出一个东西,那么就可以使用上下文菜单。

二 菜单类结构关系图

Menu                                         MenuItem菜单项              PopUpMenu 弹出菜单   
   ----ContextMenu上下文菜单 
   ----SubMenu 子菜单
说明,从上面可以看到ContextMenu、SubMenu继承了Menu(其为接口),而MenuItem是一个接口,
ContextMenu、SubMenu、Menu通过add函数添加菜单项时返回它,Menu可以通过addSubMenu函数添加一个子菜单(SubMenu),接下来就是介绍它们的具体用法了。

三 SubMenu、Menu、MenuItem、ContextMenu

1 Menu

它的常有方法:
public MenuItem add(CharSequence title);
public MenuItem add(@StringRes int titleRes);
添加一个新的菜单项
public MenuItem add(int groupId, int itemId, int order, CharSequence title);
public MenuItem add(int groupId, int itemId, int order, @StringRes int titleRes);
添加一个新的菜单项,这个菜单项将会被添加到id为groupId的菜单组
SubMenu addSubMenu(final CharSequence title);
SubMenu addSubMenu(@StringRes final int titleRes);
添加一个新的子菜单
SubMenu addSubMenu(final int groupId, final int itemId, int order, final CharSequence title);
SubMenu addSubMenu(int groupId, int itemId, int order, @StringRes int titleRes);
添加一个新的子菜单,这个子菜单将会被添加到id为groupId的菜单组

SubMenu

      SubMenu继承了Menu,它是子菜单,可以包含1~N个 MenuItem,它不支持菜单项图标,不支持子菜单。
(1)常用方法有:
public SubMenu setHeaderTitle(@StringRes int titleRes);
public SubMenu setHeaderTitle(CharSequence title);
设置菜单头的标题
public SubMenu setHeaderIcon(@DrawableRes int iconRes);
public SubMenu setHeaderIcon(Drawable icon);
设置菜单头的图标
public SubMenu setHeaderView(View view);
给菜单头添加view
public SubMenu setIcon(@DrawableRes int iconRes);
public SubMenu setIcon(Drawable icon);
设置菜单图标
(2)添加菜单
要重写 onCreateOptionsMenu 方法,如下:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
        //添加子菜单
        SubMenu subMenu = menu.addSubMenu("字体大小");
        //添加头部图标 android 3。0之后貌似就没有效果了
        subMenu.setHeaderIcon(R.mipmap.ic_launcher);
        //添加图标 android 3。0之后貌似就没有效果了
        subMenu.setIcon(R.mipmap.pic_1);
        //添加头部标题 android 3。0之后貌似就没有效果了
        subMenu.setHeaderTitle("选择字体");
        //添加菜单项, 其实返回的是 MenuItem FONT_10设置的是item的id
        subMenu.add(0,FONT_10,0,"10号");
        subMenu.add(0,FONT_12,0,"12号");
        subMenu.add(0,FONT_14,0,"14号");
        subMenu.add(0,FONT_16,0,"16号");
        subMenu.add(0,FONT_18,0,"18号");

        SubMenu colorMenu = menu.addSubMenu(0,1,0,"字体颜色");
        colorMenu.setHeaderIcon(R.mipmap.ic_launcher);
        colorMenu.setIcon(R.mipmap.pic_1);
        colorMenu.setHeaderTitle("选择字体颜色");
        colorMenu.add(0,FONT_RED,0,"红色");
        colorMenu.add(0,FONT_BLUE,0,"蓝色");
        colorMenu.add(0,FONT_GREEN,0,"绿色");
//        menu.setGroupCheckable(1,true,false);
        //关联Activity
        SubMenu intentMenu = menu.addSubMenu("启动Activity");
        intentMenu.setHeaderTitle("选择要启动的Activity");
        MenuItem menuItem = intentMenu.add("查看ViewAnimator使用");
        menuItem.setIntent(new Intent(this,ViewFlipperActivity.class));
        return super.onCreateOptionsMenu(menu);
}
(3)设置Item监听
        需要重写 onOptionsItemSelected 方法,如下:
@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case FONT_10:
                txt_menu.setTextSize(10*2);
            break;
            case FONT_12:
                txt_menu.setTextSize(12*2);
            break;
            case FONT_14:
                txt_menu.setTextSize(14*2);
                break;
            case FONT_16:
                txt_menu.setTextSize(16*2);
                break;
            case FONT_18:
                txt_menu.setTextSize(18*2);
                break;
            case FONT_RED:
                txt_menu.setTextColor(Color.RED);
                break;
            case FONT_BLUE:
                txt_menu.setTextColor(Color.BLUE);
                break;
            case FONT_GREEN:
                txt_menu.setTextColor(Color.GREEN);
                break;

        }
        return super.onOptionsItemSelected(item);
    }

ContextMenu

ContextMenu 继承了Menu, 可以包含1~N个 MenuItem,不支持菜单快捷键和 图标。
(1)常用方法有:
public ContextMenu setHeaderTitle(@StringRes int titleRes);
public ContextMenu setHeaderTitle(CharSequence title);
设置菜单头的标题
public ContextMenu setHeaderIcon(@DrawableRes int iconRes);
public ContextMenu setHeaderIcon(Drawable icon);
设置菜单头的图标
public ContextMenu setHeaderView(View view);
给菜单头添加view
(2)注册上下文菜单
   不错,上下文菜单需要注册,参数是View,当长按这个view时,将弹出菜单,如下:
//注册上下文菜单 注册后,长按txt_menu 会弹出上下文菜单,txt_menu为TextVIew对象实例
        registerForContextMenu(txt_menu);
(3)添加菜单
需要重写 onOptionsItemSelected方法,如下:
@Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
//        super.onCreateContextMenu(menu, v, menuInfo);
        //添加上下菜单
        menu.setHeaderIcon(R.mipmap.ic_launcher);
        menu.setHeaderIcon(R.mipmap.pic_1);
        menu.setHeaderTitle("选择背景色");
        menu.add(0,FONT_RED,0,"红色");
        menu.add(0,FONT_BLUE,0,"蓝色");
        menu.add(0,FONT_GREEN,0,"绿色");
    }
(4)添加监听
需要重写 onContextItemSelected方法,如下:
@Override
    public boolean onContextItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case FONT_RED:
                txt_menu.setBackgroundColor(Color.RED);
                break;
            case FONT_BLUE:
                txt_menu.setBackgroundColor(Color.BLUE);
                break;
            case FONT_GREEN:
                txt_menu.setBackgroundColor(Color.GREEN);
                break;

        }
        return super.onContextItemSelected(item);
    }
完成源码点击查看

四 使用XML文件定义菜单(推荐)

    在Java中直接使用菜单,显得比较臃肿,android使用XML文件很好的解决了这个问题。

1 标签与属性

<menu></menu>元素:菜单;
<item.../>元素:定义菜单项;
<group.../>子元素:将多个 <item.../>元素包装成一个菜单组;
<group.../>下的属性有:
checkableBehavior:指定改菜单组的选择行为,值为none(不可选)、all(多选)、single(单选);
menuCategory:指定菜单的优先级,值可为container、system、secondary、alternative;
visible:指定是否可见;
enable:指定是否可用;
<item.../> 下的属性有:
android:id:菜单项的唯一标识;
android: title:菜单项标题;
android: icon:菜单项图标;
android: alphabeticShortCut:为菜单项指定字符快捷键;
android: numericShortCut: 为菜单项指定数学快捷键;
android: checkable:指定菜单项是否可选;
android: checked:指定改菜单项默认是否已经勾选;
android: visible:指定是否可见;
android: enable:指定是否可用;

示例如下:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <!--在item下使用menu相当定义个子菜单-->
  <item android:title="字体大小" android:icon="@mipmap/ic_launcher">
      <menu>
          <!--属性checkableBehavior定义菜单行为 single 单选,all多选,none 不可选-->
          <group
              android:id="@+id/group_fount"
              android:checkableBehavior="single">
              <item android:id="@+id/fount_10" android:title="10号" />
              <item android:id="@+id/fount_12" android:title="12号" />
              <item android:id="@+id/fount_14" android:title="14号" />
              <item android:id="@+id/fount_16" android:title="16号" />
              <item android:id="@+id/fount_18" android:title="18号" />
          </group>
      </menu>
  </item>
    <item android:title="字体颜色" android:icon="@mipmap/pic_1">
        <menu>
            <group android:id="@+id/group_color"
                android:checkableBehavior="single">
                <item android:id="@+id/f_color_17" android:title="红色"/>
                <item android:id="@+id/f_color_18" android:title="蓝色"/>
                <item android:id="@+id/f_color_19" android:title="绿色"/>
            </group>
        </menu>
    </item>
</menu>

2 添加菜单

和上面一样,要重写 onCreateOptionsMenu 方法,但它需要菜单加载器MenuInflater加载布局,如下:
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = new MenuInflater(this);
        inflater.inflate(R.menu.normal_menu,menu);
        return super.onCreateOptionsMenu(menu);
    }

3 添加监听

   和上面一样 需要重写 onOptionsItemSelected 方法,然后跟菜单项的id交由不同case进行处理,如下:
@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case R.id.fount_10:
                txt_menu.setTextSize(10*2);
            break;
            case R.id.fount_12:
                txt_menu.setTextSize(12*2);
            break;
            case R.id.fount_14:
                txt_menu.setTextSize(14*2);
                break;
            case R.id.fount_16:
                txt_menu.setTextSize(16*2);
                break;
            case R.id.fount_18:
                txt_menu.setTextSize(18*2);
                break;
            case R.id.f_color_17:
                txt_menu.setTextColor(Color.RED);
                break;
            case R.id.f_color_18:
                txt_menu.setTextColor(Color.BLUE);
                break;
            case R.id.f_color_19:
                txt_menu.setTextColor(Color.GREEN);
                break;

        }
        return super.onOptionsItemSelected(item);
    }
说明,这里针对的是子菜单,那么上下为菜单也一样,不同的是它需要注册。
参考示例源码点击查看。

五 PopupMenu

     最后一个东西,弹出菜单,顾名思义它将会显示在一个view的上方或下方,使用步骤如下:
(1)调用构造函数PopupMenu(Context context,View anchor),new一个 PopupMenu对象实例, anchor是激发该菜单的组件;
(2)调用MenuInflater的inflater()的函数加载菜单XML文件;
(3)调用show()函数显示菜单;

1 创建PopupMenu对象实例

//txt_menu为TextVIew对象实例
        popupMenu = new PopupMenu(PopUpMenuTestActivity.this,txt_menu);

加载菜单XML文件

getMenuInflater().inflate(R.menu.popup_menu,popupMenu.getMenu());
XML文件如下:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <!--在item下使用menu相当定义个子菜单-->
  <item android:title="字体大小" android:icon="@mipmap/ic_launcher">
      <menu>
          <!--属性checkableBehavior定义菜单行为 single 单选,all多选,none 不可选-->
          <group
              android:id="@+id/group_fount"
              android:checkableBehavior="none">
              <item android:id="@+id/fount_10" android:title="10号" />
              <item android:id="@+id/fount_12" android:title="12号" />
              <item android:id="@+id/fount_14" android:title="14号" />
              <item android:id="@+id/fount_16" android:title="16号" />
              <item android:id="@+id/fount_18" android:title="18号" />
          </group>
      </menu>
  </item>
</menu>

激发View显示菜单

        txt_menu.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                popupMenu.show();
            }
        });

4 添加监听

popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                switch (item.getItemId()){
                    case R.id.fount_10:
                        txt_menu.setTextSize(10*2);
                        break;
                    case R.id.fount_12:
                        txt_menu.setTextSize(12*2);
                        break;
                    case R.id.fount_14:
                        txt_menu.setTextSize(14*2);
                        break;
                    case R.id.fount_16:
                        txt_menu.setTextSize(16*2);
                        break;
                    case R.id.fount_18:
                        txt_menu.setTextSize(18*2);
                        break;
                }
                return true;
            }
        });
参考 示例源码 点击查看。











 类似资料: