这几天学习了 android 里面 menu 相关的部分,边看边写了一片比较详细的,被不小心删除掉了。这里先简单记一下,以后有时间补上一篇详细的。
1. 在 xml 文件中定义 menu
可以在 res/menu 中生成一个 xml 文件来定义 menu。在定义 menu 的 xml 文件中,有三种标签可以用:<menu>,<item>,<group>。
根标签必须是 <menu>。
<item> 用于定义菜单项。在 <item> 下面可以使用 <menu> 标签来嵌套子菜单。子菜单可以嵌套多层。
<group> 是组,可以把几个 <item> 放在它下面,用于将这几个菜单项归为一个组。一个组里面的菜单项可以共享某些特定的属性, 比如 可见性 等等。
下面是他们分别可用的所有属性,属性的意义请参见谷歌文档。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@[+][package:]id/resource_name"
android:title="string"
android:titleCondensed="string"
android:icon="@[package:]drawable/drawable_resource_name"
android:onClick="method name"
android:showAsAction=["ifRoom" | "never" | "withText" | "always" | "collapseActionView"]
android:actionLayout="@[package:]layout/layout_resource_name"
android:actionViewClass="class name"
android:actionProviderClass="class name"
android:alphabeticShortcut="string"
android:numericShortcut="string"
android:checkable=["true" | "false"]
android:visible=["true" | "false"]
android:enabled=["true" | "false"]
android:menuCategory=["container" | "system" | "secondary" | "alternative"]
android:orderInCategory="integer" />
<group android:id="@[+][package:]id/resource name"
android:checkableBehavior=["none" | "all" | "single"]
android:visible=["true" | "false"]
android:enabled=["true" | "false"]
android:menuCategory=["container" | "system" | "secondary" | "alternative"]
android:orderInCategory="integer" >
<item />
</group>
<item >
<menu>
<item />
</menu>
</item>
</menu>
2. Options Menu
Options Menu 常用于放置一些对整个 app 都有比较重大的影响的菜单项。
对这种菜单来说,重要的是四个回调方法:
1)。onCreateOptionsMenu
用于创建菜单,只会在菜单创建的时候执行一次,以后不会再执行,除非手动更新菜单。在此处最好把菜单的初始化状态(比如,总共要有几个选项,不管是要显示的还是不显示的都算上)都实例化出来,程序运行过程中菜单的动态改变不要放在这里做。
2)。onPrepareOptionsMenu
这个方法在每次显示菜单之前都会调用。程序运行过程中菜单的动态改变应该放在这里做,比如判断某个选项是否应该设为不可见或未激活。
3)。onOptionsItemSelected
这个方法用来处理菜单项的点击事件。返回 true 表示处理了,返回 false 表示没处理。没处理的会返回给上一级去处理。
4)。invalidateOptionsMenu
这个方法可以引发菜单的更新,所以这就是我们用来手动更新菜单的方法。
3. PopupMenu
PopupMenu 是一个类,我们用的时候一般直接生成一个它的对象,然后让它显示。
It's useful for:
- Providing an overflow-style menu for actions that relate to specific content (such asGmail's email headers, shown in figure 4).
Note: This is not the same as a context menu, which isgenerally for actions thataffect selected content. For actions that affect selectedcontent, use thecontextual action mode orfloating context menu.
- Providing a second part of a command sentence (such as a button marked "Add"that produces a popup menu with different "Add" options).
- Providing a drop-down similar to
Spinner
that does not retaina persistent selection.
Note: PopupMenu
is available with APIlevel 11 and higher.
package com.example.menutest;
import android.os.Bundle;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.PopupMenu;
import android.widget.Toast;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@SuppressLint("NewApi")
public void showPopup(View v) {
PopupMenu menu = new PopupMenu(this, v);
menu.getMenuInflater().inflate(R.menu.activity_main, menu.getMenu());
menu.setOnMenuItemClickListener(mListener);
menu.setOnDismissListener(mDismissListener);
menu.show();
}
private PopupMenu.OnDismissListener mDismissListener = new PopupMenu.OnDismissListener() {
@Override
public void onDismiss(PopupMenu menu) {
// TODO Auto-generated method stub
}
};
private PopupMenu.OnMenuItemClickListener mListener = new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case R.id.pop:
Toast.makeText(MainActivity.this, "clicked clicked clicked",
Toast.LENGTH_SHORT).show();
break;
}
return true;
}
};
}
对应的布局文件是
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".MainActivity" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/app_name"
android:onClick="showPopup"
android:src="@drawable/ic_launcher" />
</LinearLayout>
这样就可以了吧,这个比较简单。
3. Contextual Menu
A contextual menu offers actions that affect a specific item or context frame in the UI. Youcan provide a context menu for any view, but they are most often used for items in aListView
,GridView
, or other view collections in whichthe user can perform direct actions on each item.
Contextual Menu 有两种方式:
1)。floating context menu
这种 Contextual Menu 主要是某一个view 绑定在一起,然后当触发这个view的长按事件的时候,系统会把菜单调出来。如果这个 view 是一个 listview 或者 gridview 之类的,那么你给它设置之后,你长按它的任何一个 item 都会出现一个相同的菜单。
首先,使用 registerForContextMenu(View v) 来给 v 这个 view 绑定一个 Contextual Menu,当长按的时候,会触发回调函数,产生菜单。
回调函数主要是两个:onCreateContextMenu 和 onContextItemSelected。意思一看就懂。
2)。contextual action mode
这是 3.0 以后新加的一种菜单,谷歌推荐我们使用这个。它可以绑定给某一个特定的 view,也可以绑定给整个 listview 或者 gridview。这个一般需要手动触发,触发方式应该是长按的时候或者有选项被选择的时候。
绑定一个特定view的情况:
1. 实现 ActionMode.callback 接口
2. 长按的时候调用 startActionMode 来触发菜单。
绑定整个 listview 或者 gridview的情况,以 listView 为例。
1. listview.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
2. 实例 MultiChoiceModeListener ,然后 调用 listview.setMultiChoiceModeListener 设置之。
这样当你长按listview中的某一个item的时候,就会触发菜单了。
这个说起来就比较麻烦了,看例子吧 : http://download.csdn.net/detail/wre_most2/5264250。
几点注意的:
1. 和菜单相关的回调方法的返回值都是有意义的,要慎重。
2. Options Menu 在 activity 和 fragment 中都可以注册。如果都注册了,系统会把他们的选项结合在一起显示出来。
3. 如果在 activity 和 fragment 中都注册了 Options Menu,那他们的回调函数的调用是有顺序的:先调用 activity 中的,再调用 fragment 中的。如果有多个 fragment 同时注册了menu,那么回调函数按照这些 fragment 被加入到 activity 中的顺序一次执行。