本节书摘来自异步社区《Android 平板电脑开发实战详解和典型案例》一书中的第2章,第2.6节可展开列表—— ExpandableListView,作者 吴亚峰 , 杜化美 , 索依娜,更多章节内容可以访问云栖社区“异步社区”公众号查看
2.6 可展开列表—— ExpandableListView
Android 平板电脑开发实战详解和典型案例
上一节中介绍了NumberPicker的基本知识及简单案例,本节将介绍Android 2.0控件可扩展列表ExpandableListView,主要内容包括其基本知识以及一个简单的案例。
2.6.1 可展开列表基本知识
可展开列表ExpandableListView在主界面显示的效果就是下拉菜单。当单击可展开列表ExpandableListView时会弹出一个子菜单,当再单击时界面就会恢复,使主界面节省很大的空间。可扩展列表ExpandableListView继承自ListView,其继承树如图2-28所示。
对菜单资源中的其他属性,由于篇幅所限,笔者将不再一一赘述,请读者自行查阅相关的API。
2.6.2 可展开列表使用案例
通过前面的基本知识,读者对可扩展列表的基本知识已经有了简单的了解,下面通过案例Sample2_8使读者进一步掌握可扩展列表的使用,在正式介绍此案例的开发步骤之前首先请读者了解一下本案例的运行效果,如图2-29、图2-30和图2-31所示。
图2-29为程序运行效果图,单击菜单会出现图2-30、图2-31的效果。
了解了案例的运行结果之后,下面开始介绍案例的开发,具体步骤如下。
(1)首先需要编写的是主配置文件main.xml,其代码如下。
1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:layout_width="fill_parent" <!--充满父控件-->
4 android:layout_height="fill_parent" <!--充满父控件-->
5 android:orientation="vertical" > <!--垂直放置-->
6 <ExpandableListView
7 android:id="@+id/android_list" <!--设置ID-->
8 android:layout_width=”500dip" <!--设置宽度-->
9 android:layout_height="600dip" <!--设置高度-->
10 android:layout_weight="1"
11 android:drawSelectorOnTop="false"/>
12 </LinearLayout>
该布局比较简单,在一个充满屏幕的LinearLayout中放了一个放置可展开列表ExpandableListView,单击可展开列表中的选项后可显示子列表。
(2)完成了配置文件main.xml的开发后,下面将要开发的是主Activity对应的类ExpandlActivity,其代码如下。
1 package com.bn.sample2_8; //声明包
2 ……//该处省略了部分类的导入代码,读者可自行查看随书光盘中的源代码
3 public class ExpandlActivity extends ExpandableListActivity {
4 private ExpandableListAdapter mAdapter; //声明adapter
6 @Override
7 protected void onCreate(Bundle savedInstanceState) {super.onCreate (savedInstanceState);
8 mAdapter = new MyExpandableListAdapter(); //实例化adapter
9 setListAdapter(mAdapter); //为列表设置adapter
10 registerForContextMenu(this.getExpandableListView());} //为list注册context
菜单
11 @Override //重写父类方法,当孩子被单击时调用
12 public boolean onChildClick(ExpandableListView parent, View v,
13 int groupPosition, int childPosition, long id) { Toast.makeText(this, " 组元素索引: " +
14 groupPosition + " 子元素索引: " + //显示一个Toast
15 childPosition, Toast.LENGTH_SHORT).show();
16 return super.onChildClick(parent, v, groupPosition, childPosition, id);}
17 @Override //重写父类 方法,当组被单击时调用
18 public void onGroupExpand(int groupPosition) { Toast.makeText(this, " 组元素索引: " +
//显示一个Toast
19 groupPosition, Toast.LENGTH_SHORT).show();
20 super.onGroupExpand(groupPosition);}
21 @Override //上下文菜单创建时调用
22 public void onCreateContextMenu(ContextMenu menu, View v,
23 ContextMenuInfo menuInfo) { menu.setHeaderTitle("上下文菜单");
24 menu.add(0, 0, 0, "单击我");}
25 @Override //单击上下文菜单后的逻辑
26 public boolean onContextItemSelected(MenuItem item) {
27 ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo)//获得给定菜单项的信息
28 item.getMenuInfo();
29 String title = ((TextView) info.targetView).getText().toString();
30 int type = ExpandableListView.getPackedPositionType(info.packedPosition); //获取给定的位置的类
31 if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
32 int groupPos = ExpandableListView.getPackedPositionGroup(info.packedPosition);
33 int childPos = ExpandableListView.getPackedPositionChild(info.packedPosition);
34 Toast.makeText(this, title + " 组元素索引: " + //显示一个Toast
35 groupPos + " 子元素索引: " + childPos, Toast.LENGTH_SHORT).show(); return true;}
36 else if(type == ExpandableListView.PACKED_POSITION_TYPE_GROUP){
37 int groupPos = ExpandableListView.getPackedPositionGroup(info.packed Position);
38 Toast.makeText(this, title + " 组元素索引: " + //显示一个Toast
39 groupPos, Toast.LENGTH_SHORT).show();return true;}return false;}
40 class MyExpandableListAdapter extends BaseExpandableListAdapter { //自定义Adapter
41 private String[] groups ={"我的好友","我的同学","我的家人","陌生人"}; //父列表数据
42 private String[][] children ={{ "小红","小丽","小明" },{"王强","李四" }, //子列表数据
43 { "爸爸", "妈妈", "妹妹" },{ "陌生人1", "陌生人2" }};
44 public Object getChild(int groupPosition, int childPosition) { //返回指定位置的孩子
45 return children[groupPosition][childPosition];}
46 public long getChildId(int groupPosition, int childPosition) {//获取与在给定组给定孩子的相关的数据
47 return childPosition;}
48 public int getChildrenCount(int groupPosition) { //返回在指定组的孩子数目
49 return children[groupPosition].length;}
50 public View getChildView(int groupPosition, int childPosition, //取子列表中的某一项的 View
51 boolean isLastChild, View convertView, ViewGroup parent) {
52 TextView textView = getGenericView();//取得TextView的引用
53 text.setTextSize(40);
54 text.setTextColor(ExpandlActivity.this.getResources().getColor(R.color.white);
55 textView.setText(getChild(groupPosition, childPosition).toString());//设置TextView中显示的文字
56 return textView;}
57 public Object getGroup(int groupPosition) { return groups[groupPosition];}
58 public int getGroupCount() { return groups.length;} //返回父列表的长度
59 public long getGroupId(int groupPosition) { return groupPosition;} //返回父列表指定项的位置编号
60 public View getGroupView(int groupPosition, boolean isExpanded, //取父列表中的某一项的 View
61 View convertView, ViewGroup parent) { TextView textView = getGenericView();
62 text.setTextSize(40);
63 text.setTextColor(ExpandlActivity.this.getResources().getColor(R.color.white);
64 textView.setText(getGroup(groupPosition).toString());
65 return textView;}
66 public boolean hasStableIds() { return true;} //判断指示项ID是否稳定是整个基础数据的更改
67 public boolean isChildSelectable(
68 int groupPosition, int childPosition){ return true;} //判断指定位置的子项是否可以被选择
69 private TextView getGenericView() { //获取某一项的 View 的逻辑
70 AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
71 ViewGroup.LayoutParams.FILL_PARENT, 48);
72 TextView textView = new TextView(ExpandlActivity.this);
73 textView.setLayoutParams(lp); //设置布局参数
74 textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
75 textView.setPadding(32, 0, 0, 0); //设置四周留白
76 return textView; }}}
第11~16行为当孩子被单击时调用,显示一个Toast。第17~20行为当组被单击时调用,显示一个Toast。第21~24行为上下文菜单创建时调用。
第25~39行为单击上下文菜单后的逻辑,第27~30行为获取给定菜单项的信息和给定位置的类型。第31~39行为按类型的不同显示不同的Toast。
第40~76行为自定义一个Adapter,其中第41~43行为父列表和子列表设置数据。第44~76行为获取View的逻辑。