1 在xml文件中定义选项菜单:
创建res/menu目录,并添加xml文件:选择New-Android XML File。选择Menu文件资源类型;
打开新建的xml文件,切换到xml编辑视图,添加新的item元素:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/menu_item_new_crime" android:icon="@android:drawable/ic_menu_add" android:title="@string/new_crime" android:showAsAction="ifRoom|withText" /> </menu>
为item新建资源id,在后面的响应代码中,会用到该id。showAsAction属性用于指定菜单项是显示在操作栏上,还是隐藏在溢出菜单中。选择ifRoom和withText组合值,表明如果空间足够,菜单项和文字标题都会显示,如果空间只够显示图标,则文字标题不会显示。如何访问溢出菜单,取决于具体设备。
2 创建选项菜单:
在需要选项菜单时,Android会调用activity的onCreateOptionMenu方法。不过Fragment也有一套自己的选项菜单回调函数:
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) public boolean onOptionsItemSelected(MenuItem item)
首先在Fragment类中覆盖onCreateOptionsMenu方法,通过参数inflater创建菜单:
@Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { // 该方法由托管activity的FragmentManager负责调用 // TODO Auto-generated method stub super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.fragment_crime_list, menu); }
调用超类的onCreateOptionsMenu方法属于编程规范,尽管它内部什么也不做。为了告知托管activity的FragmentManager自己有选项菜单,需要调用setHasOptionsMenu方法:
@Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setHasOptionsMenu(true); // onCreateOptionsMenu方法由托管activity的FragmentManager负责调用, // 需要借助setHasOptionsMenu方法告知FragmentManager getActivity().setTitle(R.string.crimes_title); // getActivity()返回托管activity // CrimeListFragment要显示CrimeLab中的Crime列表,需要先获取CrimeLab单例对象,进而获取其中的列表 mCrimes = CrimeLab.get(getActivity()).getCrimes(); CrimeAdapter adapter = new CrimeAdapter(mCrimes); // listview <--> adapter <--> mCrimes setListAdapter(adapter); // 为CrimeListFragment内置ListView设置adapter }
3 响应菜单选择:
若要响应选项菜单的选择,需要覆盖onOptionsItemSelected:
@Override public boolean onOptionsItemSelected(MenuItem item) { // TODO Auto-generated method stub switch(item.getItemId()) { case R.id.menu_item_new_crime: { // TODO: Add your code... return true; } default: return super.onOptionsItemSelected(item); } }
其中,R.id.menu_item_new_crime就是一开始创建的选项菜单项的id,返回true表明已经处理完所有的响应任务,如果item不是自己关系的,可以走default分支,让超类来处理。
附加内容:
如何为应用程序添加层级式导航?
现在很多应用程序,都在选项菜单的地方有一个向上的层级导航按钮,下面给出最一般的实现思路。
1 启用应用图标向上导航按钮的功能:
在Fragment.onCreateView方法调用setDisplayHomeAsUpEnable方法,设置fragment的属性。
@TargetApi(11) @Override public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) { // step4 // TODO Auto-generated method stub View v = inflater.inflate(R.layout.fragment_crime, parent, false); // 启用向上导航按钮 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { if (NavUtils.getParentActivityName(getActivity()) != null) { getActivity().getActionBar().setDisplayHomeAsUpEnabled(true); } }
这时,应用程序图标上会显示向左的图标,但点击该按钮,无响应。
2 响应向上按钮:
覆盖Fragment.onOptionsItemSelected方法:
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: { if (NavUtils.getParentActivityName(getActivity()) != null) { // 首先判断是否有父activity,有则完成跳转,这种父子关系通过Manifest注册 NavUtils.navigateUpFromSameTask(getActivity()); } return true; } default: { return super.onOptionsItemSelected(item); } } }
这里借助的是NavUtils类完成从一个activity跳转到另一个activity的导航功能。这种源到目的的关系是通过Manifest文件来注册的,例如,从Activity_A跳转到Activity_B,可以在Manifest中注册:
<activity android:name=".Activity_A" android:label="@string/app_name" > <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".Activity_B"/> </activity>