通常这种多级列表更多见于web端,移动端常见为省份选择之类的情况(类似QQ分组的通常只有两级),由于手机屏幕的限制,相当一部分也选择多个页面显示,所以也许用得不是很多,但俗话说,只有想不到的需求,没有不被要求到的需求,所以以防万一吧……
首先,最常见的为类似于省市这种形式的列表,特征是在展示前你可以获得全部数据,包括子列表,这也是最常见的多级列表形式。谷歌官方有提供ExpandableListView,可以实现两级列表,我个人以为,也这表明谷歌本身也只推荐手机端只实现两级的缩进(纯吐槽:坦白说以手机屏幕的宽度来看,在同一页面通过缩进来显示两级以上多级的层级关系真是毫无美感可言)。多级列表网上有一些实现方式,主要是前两种,都是展示前可以获得全部数据的,第三种是动态获取子列表数据时的实现方式,如下:
第一种方式:以单个listView实现,纯粹依赖缩进来造成层级效果
这种实现方式实质是以一个ListView列表来实现,无论是子列表数据还是父列表数据,展示时实际是处于同一级的,只是通过给子数据添加缩进,人为的制造出层级关系,看起来像是多级列表而已。取根列表数据资源存于代码中的firstLayerList列表,全部列表数据资源于totalList列表,但列表中每一项并不是直接的数据资源,而是数据本身、层级、数据本身id、数据父id、是否有子数据、是否已展开的一个封装对象。如:列表为List<Data>,数据为Data(String dataStr,int layer,long dataId,long dataParentId,boolean hasSubDatas,boolean isExpand);
在getView()方法中注意两点,一是根据子列表的层级计算并添加缩进,二是注意可见性,因为在convertView复用过程中有可能会复用可见性与当前项不同的view。
然后就是OnItemClickListener()方法,分三种情况:
- 若是点击项无子数据,点击不响应,return。
- 若是点击项有子数据并已展开,则响应为隐藏子数据,具体实现方式为从当前项下一项开始,以当前列表总项数为上限循环,对当前项之后的每一项作层级判断,如果layer值大于当前点击的position项的layer值,则说明为当前项的子数据、子子数据、子子子数据等,一直遍历到某一项layer值小于或等于当前选中position项的layerw值时break出循环,将遍历到的这些数据存入toDelList列表,然后通过removeAll(...)从当前列表的数据列表firstLayerList中移除toDelList列表中的所有数据项,调用notifyDataSetChanged()方法刷新列表。
- 若是点击项有子数据但未展开,则响应为展示子数据,具体实现方式为取当前点击项的dataId,遍历全部数据列表totalList,取每一项的dataParentId与当前点击项dataId比较,如果相等则说明为需要展示的子数据(当然,只是下一级子节点,好在需求也只是下一级),分别存入当前展示数据列表中的第position + i项,i从1开始累加,遍历完totalList列表后,刷新列表,会显示为展开子列表。
* 任务列表监听
*/
private AdapterView.OnItemClickListener taskItemListener = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (0 != ((Task) (mAdapter.getItem((int) id))).getSubs()) {//在没有表头的前提下,(int)id和position是一样的效果,只是个人习惯
subListView = (ListView) view.findViewById(R.id.sub_task_list);//在adapter的xml布局里,最下方包含一个<ListView ...../>,默认为隐藏状态View.GONE
//subListView.setAdapter(subAdapter);
if (View.VISIBLE == subListView.getVisibility()) {//当子listView可见时,说明是展开状态,点击时的响应就应该是关闭
subListView.setVisibility(View.GONE);
} else {//子listView不可见,则展开子列表
subListView.setVisibility(View.VISIBLE);
subListView.setFocusable(false);
subListView.setOnItemClickListener(subTaskItemListener);
}
}
};
/**
* 子任务列表监听
*/
private AdapterView.OnItemClickListener subTaskItemListener = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View subView, int position, long subId) {
if (0 != ((Task) (subAdapter.getItem((int) subId))).getSubs()) {
grandSubListView = (ListView) subView.findViewById(R.id.sub_task_list);
//grandSubListView.setAdapter(grandSubAdapter);
if (View.VISIBLE == grandSubListView.getVisibility()) {
grandSubListView.setVisibility(View.GONE);
//grandSubListView.setLayoutParams(subParentParams);
ViewGroup.LayoutParams mParentParams = subListView.getLayoutParams();
mParentParams.height -= grandSubListView.getLayoutParams().height;
subListView.setLayoutParams(mParentParams);
} else {
grandSubListView.setVisibility(View.VISIBLE);
grandSubListView.setFocusable(false);
//与以上任务列表监听相似,就不重复了
}
}
}
};