菜单Menu

前言

星光不问赶路人,时间不负有心人。

选项菜单和子菜单

Android应用中的菜单默认是看不见的,只有当用户按下手机上的“MENU”键时,系统才会显示该应用关联的菜单,这种菜单叫选项菜单。
从Android3.0开始,Android并不要求手机设备上必须提供MENU按键,在这样的情况下,Android推荐使用ActionBar来代替菜单。
下面我来简单介绍一下Menu接口定义的方法。
  • MenuItem add(int titleRes):添加一个新的菜单项。
  • MenuItem add(int groupId, int itemId, int order, CharSequence title):添加一个新的处于groupId组的菜单项。
  • MenuItem add(CharSequence title):添加一个新的菜单项。
  • SubMenu addSubMenu(int titleRes):添加一个新的子菜单。
  • SubMenu add(int groupId, int itemId, int order, CharSequence title):添加一个新的处于groupId组的子菜单。
  • SubMenu add(CharSequence title):添加一个新的子菜单。

代码示例

MainActiv.java
public class MainActivity extends Activity {

    //定义“字体大小”菜单项的标识
    final int FONT_10 = 0x111;
    final int FONT_12 = 0x112;
    final int FONT_14 = 0x113;
    final int FONT_16 = 0x114;
    final int FONT_18 = 0x115;
    //定义“普通菜单项”的标识
    final int PLAIN_ITEM = 0x11b;
    //定义“字体颜色”菜单项的标识
    final int FONT_RED = 0x116;
    final int FONT_BLUE = 0x117;
    final int FONT_GREEN = 0x118;

    private EditText edit;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.menu);
        edit = (EditText) findViewById(R.id.txt);
    }

    //当用户单击MENU建时触发该方法
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {


        //向menu中添加“字体大小”的子菜单
        SubMenu fontMenu = menu.addSubMenu("字体大小");
        //设置菜单的图标
        fontMenu.setIcon(R.drawable.ic_launcher);
        //设置菜单头的图标
        fontMenu.setHeaderIcon(R.drawable.ic_launcher);
        //设置菜单头的标题
        fontMenu.setHeaderTitle("选择字体大小");
        fontMenu.add(0, FONT_10, 0, "10号字体");
        fontMenu.add(0, FONT_12, 0, "12号字体");
        fontMenu.add(0, FONT_14, 0, "14号字体");
        fontMenu.add(0, FONT_16, 0, "16号字体");
        fontMenu.add(0, FONT_18, 0, "18号字体");
        //向menu中添加“普通菜单项”
        menu.add(0, PLAIN_ITEM, 0, "普通菜单项");
        //向menu中添加“字体颜色”的子菜单
        SubMenu colorMenu = menu.addSubMenu("字体颜色");
        colorMenu.setIcon(R.drawable.ic_launcher);
        //设置菜单头的图标
        colorMenu.setHeaderIcon(R.drawable.ic_launcher);
        //设置菜单头的标题
        colorMenu.setHeaderTitle("选择文字颜色");
        colorMenu.add(0, FONT_RED, 0, "红色");
        colorMenu.add(0, FONT_BLUE, 0, "蓝色");
        colorMenu.add(0, FONT_GREEN, 0, "绿色");

        return super.onCreateOptionsMenu(menu);
    }

    //选项菜单的菜单项被单击后的回调方法
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        //判断单击的是哪个菜单项,并有针对性地做出响应
        switch (item.getItemId()) {
        case FONT_10:
            edit.setTextSize(10 * 2);
            break;
        case FONT_12:
            edit.setTextSize(12 * 2);
            break;
        case FONT_14:
            edit.setTextSize(14 * 2);
            break;
        case FONT_16:
            edit.setTextSize(16 * 2);
            break;
        case FONT_18:
            edit.setTextSize(18 * 2);
            break;
        case FONT_RED:
            edit.setTextColor(Color.RED);
            break;
        case FONT_BLUE:
            edit.setTextColor(Color.BLUE);
            break;
        case FONT_GREEN:
            edit.setTextColor(Color.GREEN);
            break;
        case PLAIN_ITEM:
            Toast.makeText(MainActivity.this, "您单击了普通菜单项", Toast.LENGTH_SHORT).show();
            break;

        default:
            break;
        }
        return true;
    }
}

效果

Screenshot_20171024-164807.png
单击颜色菜单项
Screenshot_20171024-164812.png

上下文菜单(ContextMenu)

Android用ContextMenu来代表上下文菜单,为Android应用开发上下文菜单与开发选项菜单的方法基本相似。而开发上下文菜单与开发选项菜单的区别在于:开发上下文菜单不是重写onCreateOptionsMenu(Menu menu)方法,而是重写onCreateContextMenu(ContextMenu menu,View source, ContextMenu.ContextMenuInfo menuInfo)。其中source参数代表触发上下文菜单的组件。
开发上下文菜单的步骤如下。
  1. 重写Activity的onCreateContextMenu(ContextMenu menu, View source, ContextMenu.Context MenuInfo menuInfo)方法。

  2. 调用Activity的registerForContextMenu(View v)方法为view组件注册上下文菜单。

  3. 如果希望应用程序能为菜单项提供响应,则可以重写onContextItemSelected(MenuItem mi)方法,或为指定菜单项绑定事件监听器。

代码示例

MainActivity.java
public class MainActivity extends Activity {

    //为每个菜单定义一个标识
    final int MENU1 = 0x111;
    final int MENU2 = 0x112;
    final int MENU3 = 0x113;


    private TextView txt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.menu);
        txt = (TextView) findViewById(R.id.txt);
        //为文本框注册上下文菜单
        registerForContextMenu(txt);
    }
    //创建上下午菜单时触发该方法

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {

        menu.add(0, MENU1, 0, "红色");
        menu.add(0, MENU2, 0, "蓝色");
        menu.add(0, MENU3, 0, "绿色");
        //将三个菜单项设为单选菜单项
        menu.setGroupCheckable(0, true, true);
        //设置上下文菜单的标题、图标
        menu.setHeaderIcon(R.drawable.ic_launcher);
        menu.setHeaderTitle("选择背景色");
    }

    //上下文菜单的菜单项被单击时触发该方法

    @Override
    public boolean onContextItemSelected(MenuItem item) {

        switch (item.getItemId()) {
        case MENU1:
            item.setChecked(true);
            txt.setBackgroundColor(Color.RED);
            break;
        case MENU2:
            item.setChecked(true);
            txt.setBackgroundColor(Color.GREEN);
            break;
        case MENU3:
            item.setChecked(true);
            txt.setBackgroundColor(Color.BLUE);
            break;

        default:
            break;
        }

        return true;
    }
}

效果

Screenshot_20171025-092834.png

使用XML文件定义菜单

一般推荐使用XML资源文件来定义菜单,这种方式可以提供更好的解耦。
  • <item.../>:定义菜单项
  • <group.../>:将多个<item.../>定义的菜单项包装成一个菜单组。用于控制整组菜单的行为,该元素可指定如下常用属性。
    1. checkableBehavior:指定该组菜单的选择行为。可指定为none(不可选)、all(多选)、single(单选)。
    2. menuCategory:对菜单进行分类,指定菜单的优先级。
    3. visible:指定该组菜单是否可见。
    4. enable:指定该组菜单是否可用。

代码示例

contextmenu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <!-- 定义一组单选菜单项 -->
    <group android:checkableBehavior="single">
        <!-- 定义三个菜单项 --><!-- 字符快捷键 -->
        <item
            android:id="@+id/red"
            android:title="red_title"
            android:alphabeticShortcut="r"
            />
        <item
            android:id="@+id/green"
            android:title="green_title"
            android:alphabeticShortcut="g"
            />
        <item
            android:id="@+id/blue"
            android:title="blue_title"
            android:alphabeticShortcut="b"
            />
    </group>

</menu>

main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.zdf.uidemo9.MainActivity" >

    <item
        android:icon="@drawable/ic_launcher"
        android:title="font_size">
        <menu>

            <!-- 定义一组单选菜单项 -->
            <group android:checkableBehavior="single" >

                <!-- 定义多个菜单项 -->
                <item
                    android:id="@+id/font_10"
                    android:title="font_10"/>
                <item
                    android:id="@+id/font_12"
                    android:title="font_12"/>
                <item
                    android:id="@+id/font_14"
                    android:title="font_14"/>
                <item
                    android:id="@+id/font_16"
                    android:title="font_16"/>
                <item
                    android:id="@+id/font_18"
                    android:title="font_18"/>
            </group>
        </menu>
    </item>
    <!-- 定义一个普通菜单项 -->
    <item
        android:id="@+id/plain_item"
        android:title="plain_item"/>
    <item
        android:icon="@drawable/ic_launcher"
        android:title="font_color">
        <menu>
            <!-- 定义一组普通菜单项 -->
            <group>
                <!-- 定义三个菜单项 -->
                <item
                    android:id="@+id/red_font"
                    android:title="red_title"
                    />
                <item
                    android:id="@+id/green_font"
                    android:title="green_title"
                    />
                <item
                    android:id="@+id/blue_font"
                    android:title="blue_title"
                    />
            </group>
        </menu>
    </item>
</menu>
MainActivity.java
public class MainActivity extends Activity {

    private TextView txt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.menu);
        txt = (TextView) findViewById(R.id.txt);
        //为文本框注册上下文菜单
        registerForContextMenu(txt);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        MenuInflater inflator = new MenuInflater(this);
        inflator.inflate(R.menu.main, menu);
        return super.onCreateOptionsMenu(menu);
    }
    //创建上下文菜单时触发该方法


    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {

        MenuInflater inflator = new MenuInflater(this);
        //装填R。menu。context对应的菜单,并添加到menu中
        inflator.inflate(R.menu.context, menu);
        menu.setHeaderTitle("请选择背景色");

    }

    //上下文菜单的菜单项被单击时触发该方法

    @Override
    public boolean onContextItemSelected(MenuItem item) {

        item.setChecked(true);
        switch (item.getItemId()) {
        case R.id.red:
            item.setChecked(true);
            txt.setBackgroundColor(Color.RED);
            break;
        case R.id.green:
            item.setChecked(true);
            txt.setBackgroundColor(Color.GREEN);
            break;
        case R.id.blue:
            item.setChecked(true);
            txt.setBackgroundColor(Color.BLUE);
            break;
        }
        return true;
    }




    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if(item.isCheckable())
        {
            //勾选该菜单项
            item.setChecked(true);
        }
        //判断单击的是哪个菜单
        switch (item.getItemId()) {
        case R.id.font_10:
            txt.setTextSize(10 * 2);
            break;
        case R.id.font_12:
            txt.setTextSize(12 * 2);
            break;
        case R.id.font_14:
            txt.setTextSize(14 * 2);
            break;
        case R.id.font_16:
            txt.setTextSize(16 * 2);
            break;
        case R.id.font_18:
            txt.setTextSize(18 * 2);
            break;
        case R.id.red_font:
            txt.setTextColor(Color.RED);
            item.setChecked(true);
            break;
        case R.id.green_font:
            txt.setTextColor(Color.GREEN);
            item.setChecked(true);
            break;
        case R.id.blue_font:
            txt.setTextColor(Color.BLUE);
            item.setChecked(true);
            break;
        case R.id.plain_item:
            Toast.makeText(MainActivity.this, "您单击了普通菜单项", Toast.LENGTH_SHORT).show();
            break;
        }
        return true;
    }
}
效果和前面几个例子一样。

PopupMenu组件

PopupMenu代表弹出式菜单,它会在指定组件上弹出PopupMenu,在默认情况下,PopupMenu会显示在该组件的下方或者上方。使用PopupMenu创建菜单的步骤非常简单。
  • 调用new PopupMenu(Context context,View anchor)创建下拉菜单,anchor代表要激发该弹出菜单的组件
  • 调用MenuInflater的inflate()方法将菜单资源填充到PopupMenu中。
  • 调用PopupMenu的show()方法显示弹出式菜单。

代码示例

main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onPopupButtonClick"
        android:text="单击"
        />
</LinearLayout>

popup_main.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:title="查找"
        />
    <item
        android:title="添加"
        />
    <item
        android:title="编辑"
        />
    <item
        android:id="@+id/exit"
        android:title="隐藏菜单"
        />
</menu>
MainActivity.java
public class MainActivity extends Activity {

    PopupMenu popup = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    public void onPopupButtonClick(View button)
    {
        //创建PopupMenu对象
        popup = new PopupMenu(this, button);
        //将R。menu。popup_menu菜单资源加载到popup菜单中
        getMenuInflater().inflate(R.menu.popup_menu, popup.getMenu());
        //为popup菜单的菜单项单击事件绑定事件监听器
        popup.setOnMenuItemClickListener(new OnMenuItemClickListener() {

            @Override
            public boolean onMenuItemClick(MenuItem item) {

                switch (item.getItemId()) {
                case R.id.exit:
                    //隐藏对话框
                    popup.dismiss();
                    break;

                default:
                    Toast.makeText(MainActivity.this, "您单击了【" + item.getTitle() + "】菜单项", Toast.LENGTH_SHORT).show();
                    break;
                }
                return true;
            }
        });
        popup.show();
    }
}

效果

Screenshot_20171025-103504.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容