可展开的列表组件——ExpandableListView深入解析

一、知识点 
1、ExpandableListView常用XML属性 
2.ExpandableListView继承BaseExpandableListAdapter后重写的各个函数详解 
3.ExpandableListView自定义下拉图标

二、解析 
2.1、ExpandableListView常用XML属性

2.1.1 设置点击item项后该item项的背景色

//当你选中某一个item项时,该item项的背景会变色,下面的值是将该背景色设置为透明

android:listSelector="#00000000"

2.1.2 设置item项的高度

//这个是用在item的布局文件里
android:minHeight="50dp"

2.1.3 拖动时背景图片问题

//在拖动的时候背景图片消失变成黑色背景,等到拖动完毕我们自己的背景图片才显示出来
android:scrollingCache=”false”
或 android:cacheColorHint=”#00000000″

2.1.4 分割线高度

android:dividerHeight="1dp"

2.2ExpandableListView继承BaseExpandableListAdapter后重写的各个函数详解

下面的代码几乎每条都给了注释,就不再赘述了。

2.2.1 child.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal" > <TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"
android:textSize="18dp"
android:text="this"
/> </LinearLayout>

2.2.2 group.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="50dp"
android:orientation="horizontal" >
<ImageView
android:layout_marginLeft="10dp"
android:layout_gravity="center_vertical"
android:id="@+id/arrow"
android:layout_width="25dp"
android:layout_height="25dp"
/>
<TextView
android:layout_marginLeft="10dp"
android:id="@+id/logo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:layout_gravity="center_vertical"
/>
</LinearLayout>

2.2.3 colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="gray">#BEBEBE</color>
<color name="SeaGreen1">#54FF9F</color>
</resources>

2.2.4 activity_main.xml

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ExpandableListView
android:id="@+id/expandlist"
android:divider="@color/gray"
android:childDivider="@color/SeaGreen1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:groupIndicator="@null"
android:listSelector="#00000000"
android:dividerHeight="1dp"
> </ExpandableListView>
</LinearLayout>

2.2.5 MyExpandableListAdapter.java

package com.yds.example;

import java.util.List;
import java.util.Map; import android.content.Context;
import android.database.DataSetObserver;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ImageView;
import android.widget.TextView; public class MyExpandableListAdapter extends BaseExpandableListAdapter {
//上下文
Context context;
//声明一个布局管理器对象
LayoutInflater inflater;
//声明一个组集合
List<Map<String, Object>>group;
//声明一个子元素集合
List<List<Map<String, Object>>>child;
//声明一个map对象
Map<String, Object>map;
/**
* 自定义适配器的构造函数
* @param context 上下文
* @param group 组集合
* @param child 子元素集合
*/
public MyExpandableListAdapter(Context context,List<Map<String, Object>>group,List<List<Map<String, Object>>>child){
//初始化上下文
this.context = context;
//初始化布局管理器对象
inflater = LayoutInflater.from(context);
//初始化组集合
this.group = group;
//初始化子元素集合
this.child = child;
}
/**
* ExpandableListAdapter里面的所有条目
* 都可用吗?如果是yes,就意味着所有条目可以选择和点击了。
* 返回值:返回True表示所有条目均可用。
*/
@Override
public boolean areAllItemsEnabled() {
// TODO Auto-generated method stub
return true;
}
/**
* 获取指定组中的指定子元素数据。
*/
@Override
public Object getChild(int groupPosition, int childPosition) {
// TODO Auto-generated method stub
/*child.get(groupPosition)是得到groupPosition处的list对象,然后
* child.get(groupPosition).get(childPosition)得到child的map对象,然后
* child.get(groupPosition).get(childPosition).get("Child")是得到key值
* 为Child的值
* */
return child.get(groupPosition).get(childPosition).get("Child");
}
/**
* 获取指定组中的指定子元素ID,这个ID在组里一定是唯一的。联合ID(getCombinedChildId(long, long))在所有条目(所有组和所有元素)中也是唯一的。
*/
@Override
public long getChildId(int groupPosition, int childPosition) {
// TODO Auto-generated method stub
/******子元素的位置********/
return childPosition;
}
/**获取一个视图对象,显示指定组中的指定子元素数据。
* @param groupPosition 组位置(该组内部含有子元素)
* @param childPosition 子元素位置(决定返回哪个视图)
* @param isLastChild 子元素是否处于组中的最后一个
* @param convertView 重用已经有的视图对象,它是RecycleBin缓存机制调用getScrapView方法获取废弃已缓存的view.
* @param parent 返回的视图(View)对象始终依附于的视图组。通俗的说是它的父视图。
*/
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolderChild viewHolderChild;
/*当convertView为空,也就是没有废弃已缓存 view时,将执行下面方法,调用layoutinflate的
* inflate()方法来加载一个view。
* 如有不懂,请点击:http://blog.csdn.net/libmill/article/details/49644743
*/
if(convertView==null){
//重新加载布局
convertView = inflater.inflate(R.layout.child, null);
//初始化控件管理器(自己命名的)
viewHolderChild = new ViewHolderChild();
//绑定控件id
viewHolderChild.tv = (TextView) convertView.findViewById(R.id.tv);
/*convertView的setTag将viewHolderChild设置到Tag中,以便系统第二次绘制
ExpandableListView时从Tag中取出
*/
convertView.setTag(viewHolderChild);
}else{
//当convertView不为空时,从Tag中取出viewHolderChild
viewHolderChild = (ViewHolderChild) convertView.getTag();
}
//给子元素的TextView设置值
viewHolderChild.tv.setText(getChild(groupPosition, childPosition).toString());
//返回视图对象,这里是childPostion处的视图
return convertView;
}
/**
* 获取指定组中子元素的个数
*/
@Override
public int getChildrenCount(int groupPosition) {
// TODO Auto-generated method stub
return child.get(groupPosition).size();
}
/**
* 从列表所有项(组或子项)中获得一个唯一的子ID号。可折叠列表要求每个元素(组或子项)在所有的子元素和组中
* 有一个唯一的ID。本方法负责根据所给的子ID号和组ID号返回唯一的ID。此外,若hasStableIds()
* 是true,那么必须要返回稳定的ID。
* @param groupId 包含该子元素的组ID
* @param childId 子元素的ID
* @return:列表所有项(组或子项)中唯一的(和可能稳定)的子元素ID号。(译者注:ID理论上是稳定的,
* 不会发生冲突的情况。也就是说,这个列表会有组、子元素,它们的ID都是唯一的。)
*/
@Override
public long getCombinedChildId(long groupId , long childId ) {
// TODO Auto-generated method stub
return 0;
}
/**
* 获取组ID
* @param groupId 组ID
* @return :组ID
*/
@Override
public long getCombinedGroupId(long groupId) {
// TODO Auto-generated method stub
return 0;
}
/**
* 得到指定组的组数据
* @param groupPosition:指定的组的位置
* @return 返回指定组的组数据
*/
@Override
public Object getGroup(int groupPosition) {
// TODO Auto-generated method stub
/**group.get(groupPosition)获取map对象
* group.get(groupPosition).get("Group")获取key值为Group的数据
* **/
return group.get(groupPosition).get("Group");
}
/**
* 获取组长
*/
@Override
public int getGroupCount() {
// TODO Auto-generated method stub
return group.size();
}
/**
* 获取指定组的Id
*/
@Override
public long getGroupId(int groupPosition) {
// TODO Auto-generated method stub
return groupPosition;
}
/**
* 获取指定组的视图对象
* @param groupPosition:组位置(决定返回哪个视图)
* @param isExpanded:改组是展开状态还是伸缩状态
* @param convertView:重用已有的视图对象
* @return 返回指定组的视图对象
*/
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolderGroup viewHolder;
//判断convertView是否为空,convertView是RecycleBean调用getScrapView函数得到废弃已缓存的view
if(convertView==null){
//初始化控件管理器对象
viewHolder = new ViewHolderGroup();
//重新加载布局
convertView = inflater.inflate(R.layout.group, null);
//给组元素绑定ID
viewHolder.logo_tv = (TextView) convertView.findViewById(R.id.logo);
//给组元素箭头绑定ID
viewHolder.arrow = (ImageView) convertView.findViewById(R.id.arrow);
//convertView将viewHolder设置到Tag中,以便再次绘制ExpandableListView时从Tag中取出viewHolder;
convertView.setTag(viewHolder);
}else {//如果convertView不为空,即getScrapView得到废弃已缓存的view
//从Tag中取出之前存入的viewHolder
viewHolder = (ViewHolderGroup) convertView.getTag();
}
//设置组值
viewHolder.logo_tv.setText(getGroup(groupPosition).toString());
//如果组是展开状态
if (isExpanded) {
//箭头向下
viewHolder.arrow.setImageResource(R.drawable.arrow_down);
}else{//如果组是伸缩状态
//箭头向右
viewHolder.arrow.setImageResource(R.drawable.arrow);
}
//返回得到的指定组的视图对象
return convertView;
}
/**
* 组和子元素是否持有稳定的ID,也就是底层数据的改变不会影响到它们。
* @return 返回一个Boolean类型的值,如果为TRUE,意味着相同的ID永远引用相同的对象
*/
@Override
public boolean hasStableIds() {
// TODO Auto-generated method stub
return false;
}
/**
* 是否选中指定位置上的子元素。
*/
@Override
public boolean isChildSelectable(int arg0, int arg1) {
// TODO Auto-generated method stub
return true;
}
/**
* 如果当前适配器不包含任何数据则返回True。经常用来决定一个空视图是否应该被显示。
* 一个典型的实现将返回表达式getCount() == 0的结果,但是由于getCount()包含了头部和尾部,适配器可能需要不同的行为。
*/
@Override
public boolean isEmpty() {
// TODO Auto-generated method stub
return false;
}
/**
* 当组收缩状态的时候此方法被调用。
*/
@Override
public void onGroupCollapsed(int groupPosition) {
// TODO Auto-generated method stub }
/**
* 当组展开状态的时候此方法被调用。
*/
@Override
public void onGroupExpanded(int groupPosition) {
// TODO Auto-generated method stub }
/**
* 注册一个观察者(observer),当此适配器数据修改时即调用此观察者。
* @param observer:当数据修改时通知调用的对象
*/
@Override
public void registerDataSetObserver(DataSetObserver observer) {
// TODO Auto-generated method stub }
/**
* 取消先前通过registerDataSetObserver(DataSetObserver)方式注册进该适配器中的观察者对象。
* @param observer 取消这个观察者的注册
*/
@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
// TODO Auto-generated method stub }
/**
* 组控件管理器
* @author Administrator
*
*/
class ViewHolderGroup{
TextView logo_tv;
ImageView arrow;
}
/**
* 子控件管理器
* @author Administrator
*
*/
class ViewHolderChild{
TextView tv;
}
}

2.2.6 MainActivity.java

package com.yds.example;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import android.app.Activity;
import android.os.Bundle;
import android.widget.ExpandableListView; public class MainActivity extends Activity {
//声明一个可伸展的列表视图对象
private ExpandableListView expandlist;
//声明并初始化一个组集合对象,该集合时一个一维数组
private List<Map<String, Object>>groupList = new ArrayList<Map<String,Object>>();
//声明一个子元素集合对象,该集合是一个数组链表
private List<List<Map<String, Object>>>childList = new ArrayList<List<Map<String,Object>>>();
//声明一个子元素集合对象
private List<Map<String, Object>>child;
//声明一个map对象
private Map<String, Object>map;
//组元素值
private String[] armTypes = new String[]{
"WORD", "EXCEL", "EMAIL", "PPT"
};
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
//加载布局
setContentView(R.layout.activity_main);
//给组赋值
for (int i = 0; i < armTypes.length; i++) {
//每次都要初始化map对象
map = new HashMap<String, Object>();
//将组值放入key为Group的map中
map.put("Group", armTypes[i]);
//将map添加到组集合中
groupList.add(map);
}
//给每组的子元素赋值
for (int j = 0; j < 4; j++) {
//每次初始化子集合对象。该对象是一个一维数组
child = new ArrayList<Map<String,Object>>();
//每个组下面有25个子元素
for (int i = 0; i < 25; i++) {
//初始化map对象
map = new HashMap<String, Object>();
//将子元素的值放入key值为Child的map中
map.put("Child", "this is "+i+" example");
//将map添加到一维数组中
child.add(map);
}
//将一维数组添加到集合中
childList.add(child);
}
//可伸展的列表视图绑定ID
expandlist = (ExpandableListView) findViewById(R.id.expandlist);
//声明并初始化一个adapter
MyExpandableListAdapter adapter = new MyExpandableListAdapter(MainActivity.this,groupList,childList);
//可伸展的列表视图加载adapter
expandlist.setAdapter(adapter);
}
}

三、结果截图:

可展开的列表组件——ExpandableListView深入解析的更多相关文章

  1. ExpandableListView(可展开的列表组件)的说明以及其用法

    ExpandableListView的用法和ListView非常像,只是其所显示的列表项应该由ExpandableListAdapter提供,下面是它的xml属性及说明: 然而,接下来是用事实说话了: ...

  2. Android 可展开列表组件 ExpandableListView

    ExpandableListView 是ListView的子类,它把应用中的列表项分为几组,每组里可包含多个列表项. 所显示的列表项应该由ExpandableListAdapter 接口提供,实现Ex ...

  3. 列表组件抽象(2)-listViewBase说明

    这是我写的关于列表组件的第2篇博客.前面的相关文章有: 1. 列表组件抽象(1)-概述 listViewBase是列表组件所有文件中最核心的一个,它抽象了所有列表的公共逻辑,将来如果有必要添加其它公共 ...

  4. 【转】 HVTableView创建--展开/折叠列表能 AAShareBubbles社会分享动画组

    原文: http://blog.csdn.net/billfanggs/article/details/17279969 HVTableView HVTableView是UITableView(带有展 ...

  5. 微信小程序 - 展开收缩列表

    代码源自于:微信小程序示例官方 index.wxml <block wx:for-items="{{list}}" wx:key="{{item.id}}" ...

  6. DRF-解析器组件源码解析

    解析器组件源码解析 解析器组件源码解析 1 执行request.data 开始找重装的request中的data方法 2 在dispatch找到重装的request def dispatch(self ...

  7. 循序渐进VUE+Element 前端应用开发(8)--- 树列表组件的使用

    在我前面随笔<循序渐进VUE+Element 前端应用开发(6)--- 常规Element 界面组件的使用>里面曾经介绍过一些常规的界面组件的处理,主要介绍到单文本输入框.多文本框.下拉列 ...

  8. Vue slot 插槽用法:自定义列表组件

    Vue 框架的插槽(slot)功能相对于常用的 v-for, v-if 等指令使用频率少得多,但在实现可复用的自定义组件时十分有用.例如,如果经常使用前端组件库的话,就会经常看到类似的用法: < ...

  9. Bootstrap学习之路(3)---列表组件

    列表是几乎所有网站都会用到的一个组件,正好bootstrap也给我们提供了这个组件的样式,下面我给大家简单介绍一下bootstrap中的列表组件的用法! 首先,重提一下引用bootstrap的核心文件 ...

随机推荐

  1. Entity Framework访问MySQL数据库的存储过程并获取返回值

      一.创建MySql存储过程 1, CREATE PROCEDURE `InsertAlarmInfo`(in businessindex int, in providerindex int, in ...

  2. 关于在for循环中绑定事件打印变量i是最后一次。

    其实函数引用的外部变量都是最后一次的值. <!DOCTYPE html> <html lang="en"> <head> <meta ch ...

  3. 搭建windows下filezilla FTP服务器

    FTP服务器必不可少,鉴于serv-u越来越冗余繁多的设置,个人还是比较喜欢简单.干净,满足需求即可的东东,所以选择filezilla.更主要的原因是ta是开元免费使用的,虽然免费,功能却齐全,我发现 ...

  4. Entity Framework增删改之通用精简方法

    用EF用了好长一段时间了,从EF4.0的版本开始接触,感觉这个ORM不能说性能是最好的,但是我个人感觉功能实现以及和mvc的结合还是一个不错的企业级网站的解决方案,在此写个简易的通用扩展方法来方便大家 ...

  5. Android性能优化之运算篇

    下面是运算篇章的学习笔记,部分内容与前面的性能优化典范有重合,欢迎大家一起学习交流! 1)Intro to Compute and Memory Problems Android中的Java代码会需要 ...

  6. Asp.net Mvc4 基于Authorize实现的模块权限验证方式

    在MVC中,我们可以通过在action或者controller上设置Authorize[Role="xxx"] 的方式来设置用户对action的访问权限.显然,这样并不能满足我们的 ...

  7. SharePoint 2013中的爬网最佳做法

    了解在 SharePoint Server 2013 中爬网的最佳做法 搜索系统对内容进行爬网,以构建一个用户可以对其运行搜索查询的搜索索引.本文包含有关如何最有效地管理爬网的建议. 本文内容: 使用 ...

  8. Android学习笔记之SoftReference软引用...

    PS:其实这一篇和上一篇很类似,都是为了解决内存不足(OOM)这种情况的发生... 学习内容: 1.对象的引用类....   最近也是通过项目中知道了一些东西,涉及到了对象的引用类,对象的引用类分为多 ...

  9. Android的init过程(二):初始化语言(init.rc)解析

    Android的init过程(一) 本文使用的软件版本 Android:4.2.2 Linux内核:3.1.10 在上一篇文章中介绍了init的初始化第一阶段,也就是处理各种属性.在本文将会详细分析i ...

  10. Week4 结对编程

    1.照片 1.1  结对编程参与者:李文涛.黎柏文 1.2  展示照片 2.结对编程的优点&缺点 2.1 优点 2.1.1.两人分工合作,减少了工作量 2.1.2.结对编程的伙伴往往能提供不同 ...