菜单Menu的简单使用

本文详细探讨了Android中Menu的使用,特别是OptionMenu的注意事项。重点讲述了如何通过xml方式创建菜单,理解android:enabled属性,以及在Activity中操作菜单项的启用状态。在实践中,遇到使用findViewById获取MenuItem失败的问题,通过onOptionsItemSelected回调方法和getItem方法成功解决。同时,尝试使用LayoutInflater的inflate方法,但导致了ClassNotFoundException,揭示了Menu与layout文件夹的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

菜单Menu的使用

菜单Menu

一.OptionMenu

        1.实现步骤

                ① 在onCreateOptionsMenu(Menu menu)中创建菜单
                ② 在onOptionsItemSelected(MenuItem item)中点击事件

        2.菜单2种创建

                ① 布局样式进行加载
                    getMenuInflater().inflate(R.menu.mian_menu,menu);
                        <item
                            android:id="@+id/action1"   设置ID
                            android:title="标题一"    设置标题
                            android:orderInCategory="80"    设置排序
                            app:showAsAction="always">    设置显示方式:always总是显示     never 从不显示    ifRoom有空间就显示
                        </item>
                ② 代码实现
                    menu.add(int groupId, int itemId, int order, CharSequence title);//组号,唯一id,排序(小的在前面),标题

        3.属性

                id / title / smallIcon必须有的属性
                orderInCategory 优先级
                showAsAction  always(总是显示出来) never(不显示出来) ifRoom(有位置显示) collapseActionView withText
                withText    withText值示意Action bar要显示文本标题。Action bar会尽可能的显示这个标题,但是,如果图标有效并且受到Action bar空间的限制,文本标题有可能显示不全。    
                collapseActionView      声明了这个操作视窗应该被折叠到一个按钮中,当用户选择这个按钮时,这个操作视窗展开。否则,这个操作视窗在默认的情况下是可见的,并且即便在用于不适用的时候,也要占据操作栏的有效空间。
                一般要配合ifRoom一起使用才会有效果。


    二.ContextMenu

        1.实现步骤
                ① registerForContextMenu(View view) 为一个view注册上下文菜单
                ② onCreateContextMenu()  中生成上下文菜单
                ③ onContextItemSelected()  中响应上下文菜单项

两种菜单的区别:

        OptionMenu的拥有者是Activity,ContextMenu的拥有者是View.

OptionMenu的注意事项

在 Android菜单设计(1) : 使用xml文件布局创建 options menu文章中,初步认识了选项菜单。但是在实际开发中,还是需要注意几个问题,该篇讨论相关问题。
进入正式话题之前,需要了解一些东西。
1. 使用xml方式创建选项菜单

<?xml version="1.0" encoding="utf-8"?>

<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:id="@+id/new_game"

          android:icon="@drawable/ic_new_game"

          android:title="@string/new_game" />

    <item android:id="@+id/help"

          android:icon="@drawable/ic_help"

          android:title="@string/help" />

</menu>

需要注意:在使用menu.getItem(int index)方法时,参数index就是您在xml中创建item的顺序,如上面id为new_game的菜单就是index=0的选项,而id为help的菜单就是index=1的选项。

该方法声明:

MenuItem android.view.Menu.getItem(int index)



Gets the menu item at the given index.



Parameters:

    index The index of the menu item to return.

Returns:

    The menu item.

Throws:

    IndexOutOfBoundsException - when index < 0 || >= size()
  1. 菜单xml属性
    这里只说一个
    属性,android:enabled=[“true” | “false”],对应的方法setEable(boolean)。该属性用来设置菜单是否可用。如下图所示,左边是不可用,右边可用。

其它更加详细的文档,在sdk-path/doc/Dev Guide/Framework Topics/Application Resources/Resource Types/Menu,可以研读一下。
ok,回到主题上来。
3. 工程目录结构

  1. Activity代码
package mark.zhang;



import android.app.Activity;

import android.os.Bundle;

import android.util.Log;

import android.view.LayoutInflater;

import android.view.Menu;

import android.view.MenuInflater;

import android.view.MenuItem;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.EditText;



public class TestMenuEnableActivity extends Activity {

    private MenuItem item_ClearAll = null;



    private EditText showInfo = null;



    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        showInfo = (EditText) findViewById(R.id.testMenu_edit);



        item_ClearAll = (MenuItem) findViewById(R.id.menu_clearAll);



        findViewById(R.id.testMenu_button).setOnClickListener(new OnClickListener() {



            @Override

            public void onClick(View v) {

                if(item_ClearAll != null) {

                    item_ClearAll.setEnabled(true);

                    showInfo.setText("it enables item_ClearAll successfully!");

                } else {

                    showInfo.setText("item_ClearAll is Null,it do not enable item_ClearAll!");

                }

            }

        });

    }



@Override

    public boolean onCreateOptionsMenu(Menu menu) {

        MenuInflater inflater = getMenuInflater();

        inflater.inflate(R.menu.ui_optionsmenu, menu);

        //item_ClearAll = (MenuItem) findViewById(R.id.menu_clearAll);

        //item_ClearAll = menu.getItem(0);

        return super.onCreateOptionsMenu(menu);

    }



    ```

@Override

public boolean onOptionsItemSelected(MenuItem item) {

    switch(item.getItemId()) {

    case R.id.menu_clearAll:

        // 清除所有记录

        Log.d("mark", "clearAll");

        return true;

    case R.id.menu_help:

        // 帮助

        Log.d("mark", "help");

        return true;

    case R.id.menu_exit:

        finish();

        return true;

    default:

        return super.onOptionsItemSelected(item);

    }

}

}

  1. menu的xml文件
<?xml version="1.0"encoding="UTF-8"?>

<menu xmlns:android="http://schemas.android.com/apk/res/android"

    android:id="@+id/mymenu">



    <item android:id="@+id/menu_clearAll" android:title="清除所有记录"

        android:enabled="false" />

    <item android:id="@+id/menu_help" android:title="帮助" />

    <item android:id="@+id/menu_exit" android:title="退出" />



</menu>

注意:在这里将id为menu_clearAll的菜单设置不可用。在Activity代码中(Button点击事件)将其恢复可用。

运行应用程序,界面如下:

点击test menu,显示结果:

可以发现,使用findViewById方法无法获得菜单实例(MenuItem)对象。然后,我将代码:

item_ClearAll = (MenuItem) findViewById(R.id.menu_clearAll);
放到回调方法onCreateOptionsMenu中,修改如下:

@Override

    public boolean onCreateOptionsMenu(Menu menu) {

        MenuInflater inflater = getMenuInflater();

        inflater.inflate(R.menu.ui_optionsmenu, menu);

        item_ClearAll = (MenuItem) findViewById(R.id.menu_clearAll);

        //item_ClearAll = menu.getItem(0);

        return super.onCreateOptionsMenu(menu);

    }

再次运行,先点击手机的menu按键,确保回调onCreateOptionsMenu从而执行item_ClearAll = (MenuItem) findViewById(R.id.menu_clearAll);效果如下:

然后点击test menu,还是无法创建(MenuItem)对象。汗!
修改回调方法代码,如下:

@Override

    public boolean onCreateOptionsMenu(Menu menu) {

        MenuInflater inflater = getMenuInflater();

        inflater.inflate(R.menu.ui_optionsmenu, menu);

        //item_ClearAll = (MenuItem) findViewById(R.id.menu_clearAll);

        item_ClearAll = menu.getItem(0);

        return super.onCreateOptionsMenu(menu);

    }

可以看出,使用getItem方法创建MenuItem对象。当然,需要先点击menu按键,然后点击test menu,最后再次点击menu按键,才会有如下效果。

呵呵,创建menuItem对象成功,并且菜单已经使能。
6. 思考
使用LayoutInflater的inflate方法,试一试?

LayoutInflater inflater = LayoutInflater.from(this);

View view = inflater.inflate(R.menu.ui_optionsmenu, null);

item_ClearAll = (MenuItem)view.findViewById(R.id.menu_clearAll);
将上面代码放到回调方法onCreateOptionsMenu或者其它地方,运行之后,报异常:

08-15 06:29:48.195: ERROR/AndroidRuntime(876): Caused by: java.lang.ClassNotFoundException: android.view.menu in loader dalvik.system.PathClassLoader@44c17700

08-15 06:29:48.195: ERROR/AndroidRuntime(876): at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:243)

08-15 06:29:48.195: ERROR/AndroidRuntime(876): at java.lang.ClassLoader.loadClass(ClassLoader.java:573)

08-15 06:29:48.195: ERROR/AndroidRuntime(876): at java.lang.ClassLoader.loadClass(ClassLoader.java:532)

08-15 06:29:48.195: ERROR/AndroidRuntime(876): at android.view.LayoutInflater.createView(LayoutInflater.java:466)

08-15 06:29:48.195: ERROR/AndroidRuntime(876): at android.view.LayoutInflater.onCreateView(LayoutInflater.java:544)

08-15 06:29:48.195: ERROR/AndroidRuntime(876): at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:66)

08-15 06:29:48.195: ERROR/AndroidRuntime(876): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:563)
最后,研究了一下源码:

public View inflate(int resource, ViewGroup root, boolean attachToRoot) {

        if (DEBUG) System.out.println("INFLATING from resource: " + resource);

        XmlResourceParser parser = getContext().getResources().getLayout(resource);

        try {

            return inflate(parser, root, attachToRoot);

        } finally {

            parser.close();

        }

    }

可以看出,该方法一般是用来解析layout文件夹下面的资源文件的。而menu是res下面的一个文件夹,不属于layout。如果注意观察的话,在回调方法onCreateOptionsMenu中,使用:

MenuInflater inflater = getMenuInflater();

inflater.inflate(R.menu.ui_optionsmenu, menu);
来实例化menu这个文件夹。该inflate方法源码:

 public void inflate(int menuRes, Menu menu) {

        XmlResourceParser parser = null;

        try {

            parser = mContext.getResources().getLayout(menuRes);

            AttributeSet attrs = Xml.asAttributeSet(parser);



            parseMenu(parser, attrs, menu);

        } catch (XmlPullParserException e) {

            throw new InflateException("Error inflating menu XML", e);

        } catch (IOException e) {

            throw new InflateException("Error inflating menu XML", e);

        } finally {

            if (parser != null) parser.close();

        }

    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值