在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()

2. 菜单xml属性

这里只说一个属性,android:enabled=["true" | "false"],对应的方法setEable(boolean)。该属性用来设置菜单是否可用。如下图所示,左边是不可用,右边可用。


其它更加详细的文档,在sdk-path/doc/Dev Guide/Framework Topics/Application Resources/Resource Types/Menu,可以研读一下。

ok,回到主题上来。

3. 工程目录结构


4. 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() {@Overridepublic 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!");}}});    }        @Overridepublic 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);}@Overridepublic 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);}}}

5. 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中,修改如下:

@Overridepublic 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)对象。汗!

修改回调方法代码,如下:

@Overridepublic 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 [email protected]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();        }    }
关于menu,推荐一篇文章: http://www.cnblogs.com/xirihanlin/archive/2010/06/25/1765261.html


更多相关文章

  1. 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
  2. Android(安卓)LruCache技术原理
  3. android:theme 与 setTheme()设置透明效果并不同
  4. Handler的使用方法――在子线程中更新界面 .
  5. 通用(任何android机型)Root教程(完整版!附砖机自救方法)转自安卓
  6. Android(安卓)安全之 Activity 劫持防护
  7. Android(安卓)---- WebView与JavaScript交互调用(1)
  8. No cached version of androidx.appcompat:appcompat:1.1.0 avai
  9. Android(安卓)混淆代码学习以及Android加密工具--APKProtect的使

随机推荐

  1. Android(安卓)Gradle构建-理解DSL语言以
  2. Android(安卓)笔记:获取本机手机号(适用于
  3. 《Android和PHP开发最佳实践》一2.1 And
  4. Android(安卓)Fragment 解析
  5. Android(安卓)OkHttp完全解析 是时候来了
  6. Android内存优化全解析
  7. 【Android】Sqlite数据库增删改查
  8. Android(安卓)Binder入门指南之getServic
  9. android基础知识点总结:Android部分基础控
  10. Android中px和dip的区别