现在的位置: 首页 > 综合 > 正文

Android菜单设计(2) : options menu使用注意事项

2012年11月29日 ⁄ 综合 ⁄ 共 5953字 ⁄ 字号 评论关闭

 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() {
			
			@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);
		}
	}
}

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

@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();
        }
    }

关于menu,推荐一篇文章:http://www.cnblogs.com/xirihanlin/archive/2010/06/25/1765261.html

抱歉!评论已关闭.