Android常用控件(能折叠的ListView)--ExpandableListView的使用模仿QQ好友列表

先看效果



简介

Expandable:可张开的,就是一层ListView,点击item之后展开,里面又有一层ListView,实现的原理和ListView是一样一样的,首先,ListView需要一个数据源,而ExpandableListView是套的2个ListView,所以他需要2个数据源;其次ListView需要一个Adapter,ExpandableListView也需要一个Adapter,ListView的BaseAdapter里面重写4个方法,ExpandableListView的BaseExpandableListViewAdapter重写了10个方法,其中8个方法是和ListView里面的一样的,来看看:
LIstView的BaseAdapter:
 @Override
    public int getCount() {
        return 0;
    }

    @Override
    public Object getItem(int i) {
        return null;
    }

    @Override
    public long getItemId(int i) {
        return 0;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        return null;
    }

而ExpandableListView的 BaseExpandableListViewAdapter里面重写的方法:
 @Override
    public int getGroupCount() {
        return 0;
    }

    @Override
    public int getChildrenCount(int i) {
        return 0;
    }

    @Override
    public Object getGroup(int i) {
        return null;
    }

    @Override
    public Object getChild(int i, int i1) {
        return null;
    }

    @Override
    public long getGroupId(int i) {
        return 0;
    }

    @Override
    public long getChildId(int i, int i1) {
        return 0;
    }

    @Override
    public boolean hasStableIds() {
        return false;
    }

    @Override
    public View getGroupView(int i, boolean b, View view, ViewGroup viewGroup) {
        return null;
    }

    @Override
    public View getChildView(int i, int i1, boolean b, View view, ViewGroup viewGroup) {
        return null;
    }

    @Override
    public boolean isChildSelectable(int i, int i1) {
        return false;
    }
是不是很像,就多了两个方法,

public boolean hasStableIds(){};
是否指定分组视图及其子视图的 ID 对应的后台数据改变也会保持该 ID. 返回: 是否相同的 ID 总是指向同一个对象 .
public boolean isChildSelectable(groupPosition ,childPosition ){}

指定位置的子视图是否可选择.   参数:groupPosition 包含要取得子视图的分组位置.childPosition 分组中子视图的位置.    返回:是否子视图可选择.

属性

android:childDivider:指定各组内子类表项之间的分隔条 注:图片不会完全显示,分离子列表项的是一条直线

android:childIndicator:显示在子列表旁边的Drawable对象  注:可以是一个图片

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

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

android:groupIndicator:显示在组列表旁边的Drawable对象   注:可以是一个图片。

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

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

去掉ExpandableListView 默认的箭头

  用到ExpandableListView时有个箭头图标系统自带的在你自定义布局也不能去掉只要设置一个属性即可, settingLists.setGroupIndicator(null);  


demo实现

其他的方法和ListView的方法一样,下面来看看具体demo的实现
首先布局文件很简单,就一个控件为:


    


Activity的代码和用ListView的是一样的,创建一个adapter和两个 数据源,然后绑定,具体如下:
package com.duanlian.expendablelistviewdemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ExpandableListView;

import com.duanlian.expendablelistviewdemo.adapter.MyAdapter;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private ExpandableListView expandableListView;
    private MyAdapter myAdapter;
    private List groupList;
    private List> childList;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        expandableListView = (ExpandableListView) findViewById(R.id.expendablelistview);
        groupList = new ArrayList<>();
        childList = new ArrayList<>();
        addData("幼稚园同学",new String[]{"周杰伦","江一燕 ","佟丽娅","高圆圆","刘诗诗","刘亦菲","angleBaby","张静初","张含韵",});
        addData("小学同学",new String[]{"光头强","熊大","熊二","妙蛙种子","比卡丘","双蛋瓦斯","贪吃蛇"});
        addData("初中同学",new String[]{"苍井空","小泽玛利亚","吉泽明步","波多野结衣","爱川美里菜","小川阿佐美","桃谷绘里香","泷泽萝拉","北原多香子","石川施恩惠","北条麻妃","麻仓优","羽田爱","保坂绘里"});
        addData("高中同学",new String[]{"习近平","胡锦涛","江泽民","毛泽东","秦始皇","李世民","武则天","曹操","刘备","孙权"});
        addData("大学同学",new String[]{"周杰伦","江一燕 ","佟丽娅","高圆圆","刘诗诗","刘亦菲","angleBaby","张静初","张含韵",});
        addData("研究生同学",new String[]{"光头强","熊大","熊二","妙蛙种子","比卡丘","双蛋瓦斯","贪吃蛇"});
        addData("博士同学",new String[]{"苍井空","小泽玛利亚","吉泽明步","波多野结衣","爱川美里菜","小川阿佐美","桃谷绘里香","泷泽萝拉","北原多香子","石川施恩惠","北条麻妃","麻仓优","羽田爱","保坂绘里"});
        addData("教授同事",new String[]{"习近平","胡锦涛","江泽民","毛泽东","秦始皇","李世民","武则天","曹操","刘备","孙权"});
        addData("众仙家名册",new String[]{"苍井空","小泽玛利亚","吉泽明步","波多野结衣","爱川美里菜","小川阿佐美","桃谷绘里香","泷泽萝拉","北原多香子","石川施恩惠","北条麻妃","麻仓优","羽田爱","保坂绘里","习近平","胡锦涛","江泽民","毛泽东","秦始皇","李世民","武则天","曹操","刘备","孙权"});
        myAdapter = new MyAdapter(this,groupList,childList);
        expandableListView.setAdapter(myAdapter);

    }

    /**
     * 用来添加数据的方法
     */
    private void addData(String group, String[] friend) {
        groupList.add(group);
        //每一个item打开又是一个不同的list集合
        List childitem = new ArrayList<>();
        for (int i = 0; i < friend.length; i++) {
            childitem.add(friend[i]);
        }
        childList.add(childitem);
    }
}

然后Adapter里面需要2个item布局文件:
外层的item:



    
    


里面那层item布局:



    
    
    

其中的圆形图片,前面博客已经讲过了,就不说了

最总要的还是在Adapter里面,他和ListView一样,也有simpleAdapter和ArrayAdapter,和BaseAdapter,我这里用的是BaseAdapter,他的adapter继承的是BaseExpandableListAdapter:
package com.duanlian.expendablelistviewdemo.adapter;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.TextView;

import com.duanlian.expendablelistviewdemo.R;

import java.util.List;

/**
 * Created by duanlian on 2016/9/12.
 */
public class MyAdapter extends BaseExpandableListAdapter {
    private List groupList;//外层的数据源
    private List> childList;//里层的数据源
    private Context context;

    public MyAdapter(Context context, List groupList,List> childList ){
        this.context = context;
        this.groupList = groupList;
        this.childList = childList;
    }

    @Override
    public int getGroupCount() {
        return groupList.size();
    }

    /**
     * 这个返回的一定要是对应外层的item里面的List集合的size
     * @param groupPosition
     * @return
     */
    @Override
    public int getChildrenCount(int groupPosition) {
        return childList.get(groupPosition).size();
    }

    @Override
    public Object getGroup(int groupPosition) {
        return groupPosition;
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return childList.get(groupPosition).get(childPosition);
    }

    @Override
    public long getGroupId(int groupPosition) {
        return groupPosition;
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }

    @Override
    public boolean hasStableIds() {
        return true;
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
        convertView = View.inflate(context, R.layout.item_group, null);
        //分组名字
        TextView textView = (TextView) convertView.findViewById(R.id.group_textview);
        //子元素的个数
        TextView number = (TextView) convertView.findViewById(R.id.group_number);
        number.setText(childList.get(groupPosition).size()+"个");
        textView.setText(groupList.get(groupPosition));
        return convertView;
    }

    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View view, ViewGroup viewGroup) {
        view = View.inflate(context, R.layout.item_child, null);
        TextView textView = (TextView) view.findViewById(R.id.child_name);
        //外层的分组名字
        textView.setText(childList.get(groupPosition).get(childPosition));
        return view;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }
}


demo下载地址:http://download.csdn.net/detail/dl10210950/9629536



附加

1、首次加载全部展开:

mDownloadListView.setAdapter(mDownloadAdapter);
		for (int i = 0; i < downloadGroup.size(); i++) {
			mDownloadListView.expandGroup(i);
		}

提醒:加载前别忘了判断adapter是否为空和有没有Group数据哦、

2、不能点击收缩:

mDownloadListView.setOnGroupClickListener(new OnGroupClickListener() {
			
			@Override
			public boolean onGroupClick(ExpandableListView parent, View v,
					int groupPosition, long id) {
				// TODO Auto-generated method stub
				return true;
			}
		});

OK了,把他的组点击事件屏蔽。呵呵、

3、ExpandableListView的长按事件
网上的资料很多,但是真正管用的没几个,最后找到一个确实可以用的,在这分享下:
(1)

//长按事件
		mExpandableListView.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
			
			@Override
			public void onCreateContextMenu(ContextMenu menu, View v,
					ContextMenuInfo menuInfo) {
				// TODO Auto-generated method stub
	      menu.setHeaderTitle("选择操作");
	      menu.add(0, DOWNLOAD_RETRY, 0, "重试");
	      menu.add(0, DOWNLOAD_DEL, 0, "删除");
	      menu.add(0, DOWNLOAD_START, 0, "启动");
			}
		});

(2)

		/**
	 * 长按菜单响应函数
	 */
	@Override
	public boolean onContextItemSelected(MenuItem item) {
		// TODO Auto-generated method stub
		//关键代码
		ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) item.getMenuInfo();
		int type = ExpandableListView.getPackedPositionType(info.packedPosition);
		if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {//上面的type设定这里类型的判定!这里是child判定!
			int groupPos = ExpandableListView.getPackedPositionGroup(info.packedPosition); //在child判定里面,获取该child所属group!
			int childPos = ExpandableListView.getPackedPositionChild(info.packedPosition); //在child判定里面,获取该child所属position!
			switch (item.getItemId()) {
			case DOWNLOAD_RETRY:
				makeTextShort("我是重试");
				break;
			case DOWNLOAD_DEL:
				makeTextShort("我是删除");
				break;
			case DOWNLOAD_START:
				makeTextShort("我是启动");
			default:
				break;
			}
          return true;
		}
		return false;
	}



你可能感兴趣的:(listview,常用控件)