/*

* 记录一下方便查阅

*/

有时候,使用ListView并不能满足应用程序所需要的功能。有些应用程序需要多组ListView,这时候我们就要使用一种新的控件ExpandableListView——可以扩展的ListView。它的作用就是将ListView进行分组。就好像我们使用QQ的时候,有“我的好友”,“陌生人”,“黑名单”一样,点击一下会扩展开,再点击一下又会收缩回去。

ExpandableListView是一个垂直滚动显示两级列表项的视图,与ListView不同的是,它可以有两层:每一层都能够被独立的展开并显示其子项。这些子项来自于与该视图关联的ExpandableListAdapter。

每一个可以扩展的列表项的旁边都有一个指示符(箭头)用来说明该列表项目前的状态(这些状态一般是已经扩展开的列表项,还没有扩展开的列表项,子列表项和最后一个子列表项)。可以使用方法:setChildIndicator(Drawable),setGroupIndicator(Drawable)(或者相应的XML文件的属性) 去设置这些指示符的样式。当然也可以使用默认的指示符。布android.R.layout.simple_expandable_list_item_1,android.R.layout.simple_expandable_list_item_2

和ListView一样,ExpandableListView也是一个需要Adapter作为桥梁来取得数据的控件。一般适用于ExpandableListView的Adapter都要继承BaseExpandableListAdapter这个类,并且必须重载getGroupView和getChildView这两个最为重要的方法。

BaseExpandableListAdapter的主要重载方法如下:

public abstract ObjectgetChild (int groupPosition, int childPosition)

取得与指定分组、指定子项目关联的数据.

参数

groupPosition 包含子视图的分组的位置.

childPosition   指定的分组中的子视图的位置.

返回

与子视图关联的数据.

public abstract long getChildId (int groupPosition, intchildPosition)

取得给定分组中给定子视图的ID. 该组ID必须在组中是唯一的.必须不同于其他所有ID(分组及子项目的ID).

参数

groupPosition 包含子视图的分组的位置.

childPosition   要取得ID的指定的分组中的子视图的位置.

返回

与子视图关联的ID.

public abstract View getChildView (int groupPosition, intchildPosition, boolean isLastChild, View convertView, ViewGroup parent)

取得显示给定分组给定子位置的数据用的视图.

参数

groupPosition 包含要取得子视图的分组位置.

childPosition   分组中子视图(要返回的视图)的位置.

isLastChild     该视图是否为组中的最后一个视图.

convertView   如果可能,重用旧的视图对象.使用前你应该保证视图对象为非空,并且是否是合适的类型.如果该对象不能转换为可以正确显示数据的视图,该方法就创建新视图.不保证使用先前由 getChildView(int, int,boolean, View, ViewGroup)创建的视图.

parent     该视图最终从属的父视图.

返回

指定位置相应的子视图.

public abstract int getChildrenCount (int groupPosition)

取得指定分组的子元素数.

参数

groupPosition 要取得子元素个数的分组位置.

返回

指定分组的子元素个数.

public abstract long getCombinedChildId (long groupId, long childId)

取得一览中可以唯一识别子条目的 ID(包括分组ID和子条目ID).可扩展列表要求每个条目 (分组条目和子条目)具有一个可以唯一识别列表中子条目和分组条目的ID. 该方法根据给定子条目ID和分组条目ID返回唯一识别ID.另外,如果 hasStableIds() 为真,该函数返回的ID必须是固定不变的.

参数

groupId   包含子条目ID的分组条目ID.

childId    子条目的ID.

返回

可以在所有分组条目和子条目中唯一识别该子条目的ID(可能是固定不变的).

public abstract long getCombinedGroupId (long groupId)

取得一览中可以唯一识别子条目的 ID(包括分组ID和子条目ID).可扩展列表要求每个条目 (分组条目和子条目)具有一个可以唯一识别列表中子条目和分组条目的ID. 该方法根据给定子条目ID和分组条目ID返回唯一识别ID.另外,如果 hasStableIds() 为真,该函数返回的ID必须是固定不变的.

参数

groupId   分组条目ID.

返回

可以在所有分组条目和子条目中唯一识别该分组条目的ID(可能是固定不变的).

public abstract Object getGroup (int groupPosition)

取得与给定分组关联的数据.

参数

groupPosition 分组的位置.

返回

指定分组的数据.

public abstract int getGroupCount ()

取得分组数.

返回

分组数.

public abstract long getGroupId (int groupPosition)

取得指定分组的ID.该组ID必须在组中是唯一的.必须不同于其他所有ID(分组及子项目的ID).

参数

groupPosition 要取得ID的分组位置.

返回

与分组关联的ID.

public abstract View getGroupView (int groupPosition, booleanisExpanded, View convertView, ViewGroup parent)

取得用于显示给定分组的视图. 这个方法仅返回分组的视图对象, 要想获取子元素的视图对象,就需要调用 getChildView(int, int, boolean, View, ViewGroup).

参数

groupPosition 决定返回哪个视图的组位置 .

isExpanded     该组是展开状态还是收起状态 .

convertView   如果可能,重用旧的视图对象.使用前你应该保证视图对象为非空,并且是否是合适的类型.如果该对象不能转换为可以正确显示数据的视图,该方法就创建新视图.不保证使用先前由 getGroupView(int, boolean,View, ViewGroup)创建的视图.

parent     该视图最终从属的父视图.

返回

指定位置相应的组视图.

public abstract boolean hasStableIds ()

是否指定分组视图及其子视图的ID对应的后台数据改变也会保持该ID.

返回

是否相同的ID总是指向同一个对象.

public abstract boolean isChildSelectable (int groupPosition, intchildPosition)

指定位置的子视图是否可选择.

参数

groupPosition 包含要取得子视图的分组位置.

childPosition   分组中子视图的位置.

返回

是否子视图可选择.

注意:

在XML布局文件中,如果ExpandableListView上一级视图的大小没有严格定义的话,则不能对ExpandableListView的android:layout_height 属性使用wrap_content值。 (例如,如果上一级视图是ScrollView的话,则不应该指定wrap_content的值,因为它可以是任意的长度。不过,如果ExpandableListView的上一级视图有特定的大小的话,比如100像素,则可以使用wrap_content)

如果由于开发的时候粗心,对ExpandableListView指定wrap_content的值,则会报一个在SetContentView处的空指针错误。

根据描述,先看一个简单的例子:

定义XML的代码如下:

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:orientation="vertical" >

android:id = "@+id/myExpandableListView"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:layout_weight="1"

/>

就是在LinearLayout中布置了一个ExpandableListView。

在JAVA中的代码如下:

/*

*  Android开发之ExpandableListView

*  北京Android俱乐部群:167839253

*  Created on: 2012-7-23

*  ExpandableListViewActivity.java

*  Author: blueeagle

*/

package com.blueeagle.www;

import java.util.ArrayList;

import java.util.List;

import android.app.Activity;

import android.os.Bundle;

import android.view.Gravity;

import android.view.View;

import android.view.ViewGroup;

import android.widget.AbsListView;

import android.widget.BaseExpandableListAdapter;

import android.widget.ExpandableListView;

import android.widget.TextView;

public class ExpandableListViewActivity extends Activity {

private List GroupData;//定义组数据

private List> ChildrenData;//定义组中的子数据

private void LoadListDate() {

GroupData = new ArrayList();

GroupData.add("国家");

GroupData.add("人物");

GroupData.add("武器");

ChildrenData = new ArrayList>();

List Child1 = new ArrayList();

Child1.add("蜀国");

Child1.add("魏国");

Child1.add("吴国");

ChildrenData.add(Child1);

List Child2 = new ArrayList();

Child2.add("关羽");

Child2.add("张飞");

Child2.add("典韦");

Child2.add("吕布");

Child2.add("曹操");

Child2.add("甘宁");

Child2.add("郭嘉");

Child2.add("周瑜");

ChildrenData.add(Child2);

List Child3 = new ArrayList();

Child3.add("青龙偃月刀");

Child3.add("丈八蛇矛枪");

Child3.add("青钢剑");

Child3.add("麒麟弓");

Child3.add("银月枪");

ChildrenData.add(Child3);

}

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

LoadListDate();

ExpandableListView myExpandableListView = (ExpandableListView)findViewById(R.id.myExpandableListView);

myExpandableListView.setAdapter(new ExpandableAdapter());

}

private class ExpandableAdapter extends BaseExpandableListAdapter {

@Override

public Object getChild(int groupPosition, int childPosition) {

return ChildrenData.get(groupPosition).get(childPosition);

}

@Override

public long getChildId(int groupPosition, int childPosition) {

return 0;

}

@Override

public View getChildView(int groupPosition, int childPosition,

boolean isLastChild, View convertView, ViewGroup parent) {

TextView myText = null;

if (convertView != null) {

myText = (TextView)convertView;

myText.setText(ChildrenData.get(groupPosition).get(childPosition));

} else {

myText = createView(ChildrenData.get(groupPosition).get(childPosition));

}

return myText;

}

@Override

public int getChildrenCount(int groupPosition) {

return ChildrenData.get(groupPosition).size();

}

@Override

public Object getGroup(int groupPosition) {

return GroupData.get(groupPosition);

}

@Override

public int getGroupCount() {

return GroupData.size();

}

@Override

public long getGroupId(int groupPosition) {

return 0;

}

@Override

public View getGroupView(int groupPosition, boolean isExpanded,

View convertView, ViewGroup parent) {

TextView myText = null;

if (convertView != null) {

myText = (TextView)convertView;

myText.setText(GroupData.get(groupPosition));

} else {

myText = createView(GroupData.get(groupPosition));

}

return myText;

}

@Override

public boolean hasStableIds() {

return false;

}

@Override

public boolean isChildSelectable(int groupPosition, int childPosition) {

return false;

}

private TextView createView(String content) {

AbsListView.LayoutParams layoutParams = new AbsListView.LayoutParams(

ViewGroup.LayoutParams.FILL_PARENT, 80);

TextView myText = new TextView(ExpandableListViewActivity.this);

myText.setLayoutParams(layoutParams);

myText.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);

myText.setPadding(80, 0, 0, 0);

myText.setText(content);

return myText;

}

}

}

效果如下图所示:

这样就完成了一个最简单的ExpandableListView的控件。

在实际开发过程中,常常有不同的需求,比如每一个child需要不同的控件,每一个group或者child需要有图标,图标显示需要不一样,需要设置背景等各种各样能够让我们的程序变得美观的需求。那么下面就逐一讨论一下ExpandableListView如何实现这些需求。

比如,为ExpandableListView设置背景,并且默认展开第n组,n从0开始计数,则只需要添加如下代码:

myExpandableListView.setBackgroundResource(R.drawable.background);

myExpandableListView.expandGroup(0);

则效果如下:

改变每个组前面的图标,并且图标样式随着合拢和展开不同,则只需要在res/drawable目录下定义文件:Indicator.xml

在JAVA文件中添加:

myExpandableListView.setGroupIndicator(this.getResources().getDrawable(R.drawable.indicator));

效果如下:

对于其他的属性设置,可以参考以下属性说明:

android:childDivider

来分离子列表项的图片或者是颜色。注:图片不会完全显示,分离子列表项的是一条直线

android:childIndicator

在子列表项旁边显示的指示符。注:可以是一个图片

android:childIndicatorLeft

子列表项指示符的左边约束位置。注:即从左端0位置开始计数,比如,假设指示符是一个图标,给定这个属性值为3dip,则表示从左端起3dip开始显示此图标。

android:childIndicatorRight

子列表项指示符的右边约束位置。注:表示右端到什么位置结束

android:groupIndicator

在组列表项旁边显示的指示符。注:可以是一个图片。

android:indicatorLeft

组列表项指示器的左边约束位置。注:表示左端从什么位置开始。

android:indicatorRight

组列表项指示器的右边约束位置。注:表示右端到什么位置结束。

当然,还可以使用自定义的View去描述group和child,自定义的View可以和布局文件一样,写在layout文件夹下。例如命名为group.xml或者child.xml。

例如,我们定义一个child项由一个ImageView和一个TextView来组成,则可以定义child.xml为:

xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation = "horizontal"

android:layout_width="match_parent"

android:layout_height="match_parent">

android:layout_gravity = "center_vertical"

android:id = "@+id/imageView01"

android:layout_width = "70px"

android:layout_height = "70px"

android:paddingLeft = "30px"

android:paddingTop = "2px"

android:paddingBottom = "5px"

android:src = "@drawable/ic_launcher"/>

android:layout_gravity = "center_vertical"

android:id = "@+id/childTV"

android:layout_width = "match_parent"

android:layout_height = "match_parent"

android:paddingLeft = "30px"

android:paddingTop = "10px"

android:paddingBottom = "5px"

android:textSize = "30sp"/>

对于其中的属性不再做详细说明。

对于ExpandableListView中的数据,还可以用以下方式定义:

List> groups = new ArrayList>();

Map group1 = new HashMap();

group1.put("group", "国家");

… …

groups.add(group1);

… …

//准备第一个一级列表中的二级列表数据:三个二级列表,分别显示"魏国"、"蜀国"和"吴国"

List> child1 = new ArrayList>();

Map child1Data1 = new HashMap();

child1Data1.put("child", "魏国");

… …

child1.add(child1Data1);

… …

//准备第二个一级列表中的二级列表数据:八个二级列表,显示"关羽"、"张飞"、"典韦"、"吕布"、"曹操"、"甘宁"、"郭嘉"、"周瑜"

List> child2 = new ArrayList>();

Map child2Data1 = new HashMap();

child2Data1.put("child", "关羽");

… …

child2.add(child2Data1);

… …

//准备第三个一级列表中的二级列表数据:五个二级列表,显示 "青龙偃月刀"、"丈八蛇矛枪"、 "青钢剑"、"麒麟弓"、"银月枪"

List> child3 = new ArrayList>();

Map child3Data1 = new HashMap();

child3Data1.put("child", "青龙偃月刀");

… …

child3.add(child3Data1);

… …

//用一个list对象保存所有的二级列表数据

List>> childs = new ArrayList>>();

childs.add(child1);

childs.add(child2);

childs.add(child3);

针对上述数据定义方式,修改java文件:

例如:在getChildView函数中做如下编写,

String text = groups.get(groupPosition).get("group");

LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

//获取一级列表布局文件,设置相应元素属性

LinearLayout linearLayout = (LinearLayout) layoutInflater.inflate(R.layout.group, null);

TextView textView = (TextView)linearLayout.findViewById(R.id.textView01);

textView.setText(text);

return linearLayout;

这样就可以将自定义的View写入到child中,当然,这里也可以不用布局文件来定义View,也可以自己用代码实现View。

补充知识:

对于ExpandableListView相应的,也有一个ExpandableListActivity与之对应,对于只需要一个ExpandableListView的Activity,则只需要使用ExpandableListActivity来完成相应的功能就可以了。但是需要注意一点的是:在main.xml页面中添加如下代码:

android:layout_width="fill_parent"

android:layout_height="wrap_content">

这个ID不能随便修改,否则会出现异常:java.lang.RuntimeException:Your content must have a ExpandableListView whose id attribute is'android.R.id.list'.

java list套listview_ExpandableListView讲解(ListView的子类其作用类似于两个ListView的嵌套)...相关推荐

  1. “万字“ Java I/O流讲解

    Java I/O流讲解 每博一文案 谁让你读了这么多书,又知道了双水村以外还有一个大世界,如果从小你就在这个天地里,日出而作,日落而息. 那你现在就会和众乡亲抱同一理想:经过几年的辛劳,像大哥一样娶个 ...

  2. java 内存例子_简单的例子 关于Java内存管理的讲解

    我想做的是,逐行读取文件,然后用该行的电影名去获取电影信息.因为源文件较大,readlines()不能完全读取所有电影名,所以我们逐行读取. 就这段代码,我想要在位置二处使用base64,然后结果呢? ...

  3. java原子变量的作用_AtomicInteger原子类的作用介绍(代码示例)

    本篇文章给大家带来的内容是关于AtomicInteger原子类的作用介绍(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. AtomicInteger 原子类的作用 多线程操 ...

  4. Java经典面试套路讲解:Java Killer系列

    Java经典面试套路讲解:Java Killer系列 java编程语言是目前应用较为广泛的一门计算机编程语言,目前java市场需求量有增无减.java作为目前IT软件开发行业的重要技术之一,人才市场出 ...

  5. JAVA UDP套接字编程

    JAVA UDP套接字编程 UDP套接字 无连接 非可靠传输 面向数据报 package com.lius.udp;import java.io.IOException; import java.ne ...

  6. Java高效输入输出流讲解

    Java高效输入输出流讲解 Java中执行输出和输入操作,需要通过IO流.例如最常见的System.out.println()就是一个输出流.IO流的类比较多,但核心体系就是由File. InputS ...

  7. Java语言基础详细讲解

    就像人与人之间交流使用的语言需要遵循一定的语法规则一样,Java语言也离不开特定语法的支持,如基本语法.数据类型.变量.常量.运算符与表达式.类型转换和输入输出等,只不过这些语法要比日常生活中语言的语 ...

  8. Java中父类的静态方法能否被子类重写?

    Java中父类的静态方法能否被子类重写 前言 一.final关键字和static关键字介绍 二.问题产生及解决 1.错误结论 2.正确结论及验证 总结 前言 今天在复习final关键字的时候突发奇想, ...

  9. java解析遍历List集合(其实现子类)的三种方式

    java解析遍历List集合(其实现子类)的三种方式 1 使用迭代器对象 1.1 底层 1.1.1 List接口继承了Collection接口 1.1.2 而Collection接口又继承了Itera ...

最新文章

  1. C#中static静态变量的用法
  2. Affinity Photo中文版
  3. 只因这个模型,它 1 年增长 44%,收入达 2.15 亿美元
  4. 获取顶级常量、祖先链、私有方法
  5. java不输出数字_为什么我的代码不输出(仅)数字?
  6. 一个程序员年近四十岁的一些胡思乱想
  7. Cloud一分钟 | 蚂蚁金服估值超万亿;Google大举进军游戏市场
  8. bootsrap 外边距_Bootstrap 网格系统布局详解
  9. 什么时候学习编程都不晚
  10. signature=45ca03a07a2e888fb57b0d2c351110d7,Attention: Docket Number H054a Dec. 31,2004
  11. Android开发实战记录
  12. 社区版PyCharm(PyCharm Community)也可以有可视化的数据库工具呀
  13. 计算机ps相框怎么做,教你用PS给相片加上很漂亮的相框
  14. 2022微软中国在苏州北京上海等城市共有700多职位热招,欢迎自荐推荐转发
  15. 每秒订单数25倍提升,蘑菇街怎样跨过海量服务架构的技术藩篱?
  16. 机械式计算机自制,自制计算机(1):机械计算机原理
  17. 如何解决飞思卡尔芯片使用监控程序产生的冲突问题
  18. idea 使用 Docker 打包镜像的两种方式_07
  19. 数值策划到底需要多高的水平
  20. Bongo Cat(手鼓猫)配置文件及部分使用教程

热门文章

  1. 2008上海英雄会,英雄如是说
  2. 【分页存储管理】将十六进制的虚拟地址0A5C、103C、4251转换成物理地址
  3. 刚毕业的小白想学软件测试,有没有好的机构推荐呢?
  4. UG8 安装指南,带详细教学视频
  5. 阿里云学生成长计划领取资格考试答案
  6. 十六进制转八进制(C语言版)
  7. 怎么给图片添加水印?
  8. 拼多多有哪些API?
  9. 计算机里为什么显示cpu主频高,cpu主频显示不对是什么原因怎么解决
  10. Tensorflow2数据集过大,GPU内存不够