应用系统中最常见的组织功能的方式之一就是菜单。 Android系统中有两种菜单:OptionMenu和ContextMenu. OptionMenu就是点击Menu按钮时显示的菜单(在3.0以后的版本,可能没有Menu按钮,而是由一个Action Bar). ContextMenu是指用户长时间按住屏幕时显示的Menu(在3.0以后的版本中,Android推荐使用ActionMode).
以我们的餐馆系统为例,在餐馆列表界面,我们需要两种菜单。当用户点击菜单按钮时,需要显示[新建]这个菜单,在用户长时间按住某个餐馆时,我们要显示一个Context菜单。这个Context菜单包括[新建],[编辑],[删除]三项。如果餐馆是金牌餐馆,那么不能直接删除,所以此时删除菜单要禁用。
Android系统中,如果需要使用Menu按钮,
- 首先需要重写onCreateOptionsMenu来响应用户点击菜单按钮的事件
- 重写onOptionsItemSelected来响应菜单项点击事件。
但是我们的这个例子中还用到了onPrepareOptionsMenu。这个方法在每次菜单显示之前执行。我们使用这个事件的原因是我们的Options Menu和Contextual Menu使用的是同一个菜单资源文件,我们需要在这里通过代码隐藏更新和删除菜单项(因为我们没有提供选择功能)。
使用Context菜单的流程有点不同。对于我们的ListView而言,
- 首先调用Activity的registerForContextMenu方法通知Activity,我们的ListView需要使用ContextMenu.
- 然后重写onCreateContextMenu,当用户长按住ListView的时候,这个方法会被调用来创建菜单。
- 最后重写onContextItemSelected处理事件响应, 当用户点击了菜单项的时候,Android调用这个方法。
最后要提到的一件事,其实是应该最先做的,那就是定义菜单资源文件。
菜单资源文件
我在res文件夹下新建了一个menu文件夹。然后新建了一个restaurant_list_view.xml。下面是文件内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
item
android:id
=
"@+id/r000_create_restaurant"
android:title
=
"新建"
>
</
item
>
<
item
android:id
=
"@+id/r000_update_restaurant"
android:title
=
"编辑"
>
</
item
>
<
item
android:id
=
"@+id/r000_delete_restaurant"
android:title
=
"删除"
>
</
item
>
</
menu
>
|
使用Option Menu
按照前面的介绍,我们需要重写下面的三个方法,方法的内容都很简单,就不需要再介绍了.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
@Override
public
boolean
onCreateOptionsMenu(Menu menu) {
new
MenuInflater(
this
).inflate(R.menu.restaurant_list_form, menu);
return
super
.onCreateOptionsMenu(menu);
}
@Override
public
boolean
onPrepareOptionsMenu(Menu menu){
menu.findItem(R.id.r000_delete_restaurant).setVisible(
false
);
menu.findItem(R.id.r000_update_restaurant).setVisible(
false
);
return
super
.onPrepareOptionsMenu(menu);
}
@Override
public
boolean
onOptionsItemSelected(MenuItem item) {
if
(item.getItemId() == R.id.r000_create_restaurant) {
Intent intent =
new
Intent(
this
, RestaurantDetailsEditor.
class
);
this
.startActivityForResult(intent, RequestCode_CreateRestaurant);
}
return
super
.onOptionsItemSelected(item);
}
|
使用Context Menu
按照前面的介绍,我们需要写的代码分为三部分.下面是具体的代码。这段代码通过getSelectedRestaurant方法演示了如何使用onCreateContextMenu的menuInfo这个参数。如果同一个界面上有多个View需要Context Menu,那么view这个参数也要用上才可以。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.main);
this
.restaurantDataProvider =
new
MemoryRestaurantDataProvider();
this
.restaurantListView = (ListView) findViewById(R.id.restaurant_list_view);
this
.restaurantListAdapter =
new
RestaurantListAdapter(
this
,
this
.restaurantDataProvider.getRestaurants());
this
.restaurantListView.setAdapter(
this
.restaurantListAdapter);
this
.restaurantListView.setOnItemSelectedListener(onRestaurantSelected);
this
.restaurantListView.setOnItemClickListener(onItemClicked);
this
.registerForContextMenu(
this
.restaurantListView);
}
@Override
public
void
onCreateContextMenu(ContextMenu menu, View view,
ContextMenuInfo menuInfo) {
super
.onCreateContextMenu(menu, view, menuInfo);
Restaurant dataItem = getSelectedRestaurant(menuInfo);
if
(dataItem !=
null
) {
this
.getMenuInflater().inflate(R.menu.restaurant_list_form, menu);
menu.findItem(R.id.r000_delete_restaurant).setEnabled(
!dataItem.isGoldenBrand());
}
}
private
Restaurant getSelectedRestaurant(ContextMenuInfo menuInfo) {
Restaurant dataItem =
null
;
AdapterContextMenuInfo adapterMenuInfo = (AdapterContextMenuInfo) menuInfo;
dataItem =
this
.restaurantListAdapter.getItem(adapterMenuInfo.position);
return
dataItem;
}
@Override
public
boolean
onContextItemSelected(MenuItem item) {
switch
(item.getItemId()) {
case
R.id.r000_update_restaurant:
break
;
case
R.id.r000_delete_restaurant:
break
;
}
return
super
.onContextItemSelected(item);
}
|
显示效果
运行效果截图: