ExpandableListView是一个用来显示二级节点的listview。

qq好友列表中子列表上下移动时,父节点在顶端会始终显示,这里我们可以自定义一个view来充当这个父节点。

 

主布局文件qq_listview如下,其中当我们拖动列表时,系统默认拖动过程中列表背景是黑的,我们可以通过android:cacheColorHint="#00000000"将其设置为透明,其中前两位是透明效果参数(00-99),后六位是颜色的设置。

 


Xml代码

1. <?xml version="1.0" encoding="utf-8"?>
2. <LinearLayout
3. xmlns:android="http://schemas.android.com/apk/res/android"
4. android:layout_width="fill_parent"
5. android:layout_height="wrap_content"
6. android:orientation="vertical"
7. android:background="@drawable/default_bg_hdpi">
8. <LinearLayout
9. android:id="@+id/gone_linear"
10. android:layout_width="fill_parent"
11. android:layout_height="wrap_content"
12. android:background="@drawable/expand_column_bg"
13. android:visibility="gone"
14. android:cacheColorHint="#50000000"
15. >
16. <ImageView android:id="@+id/qq_list_imageview"
17. android:layout_width="wrap_content" android:layout_height="30dip"
18. android:src="@drawable/narrow_select" />
19. <TextView android:id="@+id/qq_list_textview" android:layout_marginLeft="50dip"
20. android:layout_width="fill_parent" android:layout_height="wrap_content" />
21. </LinearLayout>
22. <FrameLayout android:layout_width="fill_parent"
23. android:layout_height="fill_parent">
24. <ExpandableListView android:id="@+id/qq_listview"
25. android:cacheColorHint="#00000000"
26. android:layout_width="fill_parent" android:layout_height="wrap_content" />
27. </FrameLayout>
28. </LinearLayout>

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@drawable/default_bg_hdpi">
<LinearLayout
android:id="@+id/gone_linear"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/expand_column_bg"
android:visibility="gone"
android:cacheColorHint="#50000000"
>
<ImageView android:id="@+id/qq_list_imageview"
android:layout_width="wrap_content" android:layout_height="30dip"
android:src="@drawable/narrow_select" />
<TextView android:id="@+id/qq_list_textview" android:layout_marginLeft="50dip"
android:layout_width="fill_parent" android:layout_height="wrap_content" />
</LinearLayout>
<FrameLayout android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ExpandableListView android:id="@+id/qq_listview"
android:cacheColorHint="#00000000"
android:layout_width="fill_parent" android:layout_height="wrap_content" />
</FrameLayout>
</LinearLayout>


 

如果我们想更换父节点打开和关闭时的箭头,可以先设置一个selector.xml

 


Java代码


<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_window_focused="false" android:drawable="@drawable/expand_column_bg_over" />
<item android:state_pressed="true" android:drawable="@drawable/expand_column_bg" />
<item android:state_pressed="false" android:drawable="@drawable/feedlistdividerbg"></item>
</selector>

 然后在代码中调用

 


Java代码

elistview = (ExpandableListView)findViewById(R.id.qq_listview);
//替换ExpandableListView的打开关闭时的箭头图标
elistview.setGroupIndicator(this.getResources().getDrawable(R.drawable.expand_list_selector));

 

此外,我们还要设置父节点和子节点item的布局文件

父节点qq_list_parent.xml如下

 


Java代码


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/expand_column_bg">
<TextView android:id="@+id/parend"
android:layout_width="wrap_content"
android:layout_height="30dip"
android:layout_marginLeft="50dip"
/>
</LinearLayout>

 

子节点qq_listview_child.xml

 


Java代码


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:cacheColorHint="#00000000"
>
<TextView android:id="@+id/child"
android:layout_width="wrap_content" android:layout_height="40dip"
android:layout_marginLeft="80dip"
/>
</LinearLayout>

 

java代码如下

 


Java代码


package com.sy.android.qqlistview;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnGroupCollapseListener;
import android.widget.ExpandableListView.OnGroupExpandListener;
import android.widget.LinearLayout;
import android.widget.SimpleExpandableListAdapter;
import android.widget.TextView;

import com.sy.android.testAndroid.R;

public class QQListView extends Activity {

private static ArrayList<Map<String,String>> parentData = new ArrayList<Map<String,String>>();
private static ArrayList<ArrayList<Map<String,String>>> childData = new ArrayList<ArrayList<Map<String,String>>>();
private ExpandableListView elistview;
private TextView tv;

/**
*当前打开的父节点
*/
private int the_group_expand_position=-1;
/**
* 打开的父节点所与的子节点数
*/
private int position_child_count=0;
/**
* 是否有打开的父节点
*/
private boolean isExpanding=false;

public void getData(){
for(int i=0; i<20;i++){
Map<String,String> map = new HashMap<String,String>();
map.put("parend", i+"");
parentData.add(map);
}
for(int i=0;i<20;i++){
ArrayList<Map<String,String>> child = new ArrayList<Map<String,String>>();
for(int j=0; j<20;j++){
Map<String,String> map = new HashMap<String,String>();
map.put("child", i+""+j);
child.add(map);
}
childData.add(child);
}
}

public void onCreate(Bundle saveBundle){
super.onCreate(saveBundle);
setContentView(R.layout.qq_listview);

elistview = (ExpandableListView)findViewById(R.id.qq_listview);
//替换ExpandableListView的打开关闭时的箭头图标
elistview.setGroupIndicator(this.getResources().getDrawable(R.drawable.expand_list_selector));
tv = (TextView)findViewById(R.id.qq_list_textview);

/**
* 滑动子列表时在上方显示父节点的view
*/
final LinearLayout linear = (LinearLayout)findViewById(R.id.gone_linear);

/**
* 监听父节点打开的事件
*/
elistview.setOnGroupExpandListener(new OnGroupExpandListener(){

@Override
public void onGroupExpand(int groupPosition) {
the_group_expand_position=groupPosition;
position_child_count=childData.get(groupPosition).size();
isExpanding=true;
}

});

/**
* 监听父节点关闭的事件
*/
elistview.setOnGroupCollapseListener(new OnGroupCollapseListener(){

@Override
public void onGroupCollapse(int groupPosition) {
if(linear.getVisibility()==View.VISIBLE){
linear.setVisibility(View.GONE);
}
isExpanding=false;
}

});


linear.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View v) {
linear.setVisibility(View.GONE);
elistview.collapseGroup(the_group_expand_position);
}

});

/**
* 通过setOnScrollListener来监听列表上下滑动时item显示和消失的事件
*/

elistview.setOnScrollListener(new OnScrollListener(){

@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {

}

@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if(isExpanding){
// 当当前第一个item id小于打开的父节点id 或大于打开的父节点id和它的子节点总数之和时
if(firstVisibleItem<the_group_expand_position ||
firstVisibleItem>(the_group_expand_position+position_child_count)){
linear.setVisibility(View.GONE);
}else{
linear.setVisibility(View.VISIBLE);
tv.setText(((Map)parentData.get(the_group_expand_position)).get("parend").toString());
}
}
}

});

getData();

SimpleExpandableListAdapter selAdapter = new SimpleExpandableListAdapter(this,
parentData,
R.layout.qq_listview_parend_item,
new String[]{"parend"},
new int[]{R.id.parend},
childData,
R.layout.qq_liatview_child_item,
new String[]{"child"},
new int[]{R.id.child}
);
elistview.setAdapter(selAdapter);

}

}

 

 

实现的思路是通过setOnScrollListener来监听listview,从而获得显示在视图中的item的id,通过id的判断来决定显示在顶端的自定义的view是否显示