ListView是Android开发里最常用的控件,但最近开发的音乐播放器需要把歌曲[按首字母分类并排序]显示,这时就需要用到ExpandableListView.
效果图:
:
首先,需要重写BaseExpandableListAdapter这个专门对应ExpandableListView的适配器类,其中最主要的是实现getGroupView和getChildView这两个函数,它们返回的View实例最终会显示在ExpandableListView上的父item和父item对应的子item上.
父item的布局文件group_item.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="match_parent"
android:orientation="vertical"
android:background="#dadada"
>
<TextView
android:id="@+id/group_text"
android:layout_width="match_parent"
android:layout_height="24dip"
android:text="A"
android:textSize="20sp"
android:textColor="#FFFFFF"
android:paddingLeft="8dp"
/>
</LinearLayout>
getGroupView函数:
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
if(convertView==null){
convertView=inflater.inflate(R.layout.group_item, null);
//设置为true,点击后就没有相应了!!!
convertView.setClickable(true);
}
TextView textView=(TextView)convertView.findViewById(R.id.group_text);
textView.setText(helper.getFirstChar(helper.getHashList()
.getChild(groupPosition, 0).getTitle()));
//convertView.setVisibility(View.GONE);
return convertView;
}
子item的布局文件:
<?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:orientation="horizontal">
<CheckBox
android:id="@+id/child_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:layout_gravity="center_vertical"
android:visibility="gone"
/>
<ImageView
android:id="@+id/child_albumView"
android:layout_width="64dp"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:visibility="gone"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="32dp"
<span style="white-space:pre"> </span> android:paddingLeft="8dp"
>
<ImageView
android:id="@+id/playingView"
android:layout_width="wrap_content"
<span style="white-space:pre"> </span> android:layout_height="wrap_content"
<span style="white-space:pre"> </span> android:src="@drawable/thumb_dn"
<span style="white-space:pre"> </span> android:layout_alignParentBottom="true"
<span style="white-space:pre"> </span> android:layout_alignParentLeft="true"
<span style="white-space:pre"> </span> android:visibility="gone"
/>
<TextView
<span style="white-space:pre"> </span> android:id="@+id/child_titleText"
<span style="white-space:pre"> </span> android:layout_width="wrap_content"
<span style="white-space:pre"> </span> android:layout_height="wrap_content"
<span style="white-space:pre"> </span> android:layout_alignParentBottom="true"
<span style="white-space:pre"> </span> android:text="guoke"
<span style="white-space:pre"> </span> android:textSize="15sp"
<span style="white-space:pre"> </span> android:layout_toRightOf="@+id/playingView"
<span style="white-space:pre"> </span> android:ellipsize="marquee"
android:lines="1"
android:singleLine="true"
android:marqueeRepeatLimit="marquee_forever"
/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="32dp"
<span style="white-space:pre"> </span> android:paddingLeft="8dp"
>
<TextView
<span style="white-space:pre"> </span> android:id="@+id/child_artisanAndAlbumText"
<span style="white-space:pre"> </span> android:layout_width="wrap_content"
<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>android:layout_height="wrap_content"
<span style="white-space:pre"> </span> android:layout_centerVertical="true"
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span> android:text="guoke2"
<span style="white-space:pre"> </span> android:textSize="13sp"
<span style="white-space:pre"> </span> android:textColor="#8f8d8c"
<span style="white-space:pre"> </span> android:ellipsize="marquee"
android:lines="1"
android:singleLine="true"
android:marqueeRepeatLimit="marquee_forever"
/>
</RelativeLayout>
</LinearLayout>
</LinearLayout>
getChildView函数代码:
<span style="font-size:14px;"><span style="font-size:14px;"> public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder = null;//用来绑定和操作每一item的控件
if(convertView==null){
convertView=inflater.inflate(R.layout.child_item, null);
holder=new ViewHolder();
holder.titleView=(TextView)convertView.findViewById(R.id.child_titleText);
holder.artistAndAlbumView=(TextView)convertView.findViewById(R.id.child_artisanAndAlbumText);
holder.albumView=(ImageView)convertView.findViewById(R.id.child_albumView);
holder.playingView=(ImageView)convertView.findViewById(R.id.playingView);
holder.checkBox=(CheckBox)convertView.findViewById(R.id.child_checkbox);
convertView.setTag(holder);
//此处设置为true,item将不能点击
//convertView.setClickable(true);
}else{
holder=(ViewHolder)convertView.getTag();
}
<span style="color:#ff0000;font-size:14px;">Mp3Info tInfo=helper.getHashList().getChild(groupPosition, childPosition);</span>
//显示歌曲名,艺术家名和专辑名
<span style="color:#ff0000;font-size:14px;">holder.titleView.setText(tInfo.getTitle());
holder.artistAndAlbumView.setText(tInfo.getArtist()+"-"+tInfo.getAlbum());</span>
//显示封面专辑,滑动的时候会卡
//showAlbum(tInfo, holder);//显示专辑封面
if(tInfo.getIsPrePare()==true){
holder.playingView.setVisibility(View.VISIBLE);
}else{
holder.playingView.setVisibility(View.GONE);
}
//System.out.println("getChildView被调用"+"playingView的可见性为:"+holder.playingView.getVisibility());
//控制checkbox的显示
if(stateFlag==GENERALSTATE){//常规状态不显示
holder.checkBox.setVisibility(View.GONE);
}else{//编辑状态才显示
holder.checkBox.setVisibility(View.VISIBLE);
holder.checkBox.setChecked(tInfo.getIschecked());
}
return convertView;
}</span></span>
可以看到在getChildView()函数里主要是对 titleView 和 artistAndAlbumView 这两个控件赋值, checkBox 只在编辑状态下才显示, albumView 因为滑动的时候会卡而取消它的显示, playingView 只有正在播放的歌曲的那一个item才会显示.
需要注意的是这一行代码:Mp3Info tInfo=helper.getHashList().getChild(groupPosition, childPosition);
helper是Mp3SortHelper类的一个实例,HashList类是一个对相关数据封装的类,而Mp3SortHelper类则封装了操作HashList的函数.这个后面再详细介绍.
public final class ViewHolder{
<span style="white-space:pre"> </span>TextView titleView;//歌曲名
<span style="white-space:pre"> </span>TextView artistAndAlbumView;//艺术家名和专辑名
<span style="white-space:pre"> </span> public CheckBox checkBox;
<span style="white-space:pre"> </span>ImageView albumView;//专辑图片
<span style="white-space:pre"> </span>ImageView playingView;//播放的小标志
<span style="white-space:pre"> </span>}
此外 BaseExpandableListAdapter中还有一些必须重写的函数:
@Override
public int getGroupCount() {
// TODO Auto-generated method stub
return helper.getHashList().size();
}
@Override
public int getChildrenCount(int groupPosition) {
// TODO Auto-generated method stub
return helper.getHashList().getChildList(groupPosition).size();
}
@Override
public Object getGroup(int groupPosition) {
// TODO Auto-generated method stub
return helper.getHashList().getKeyIndex(groupPosition);
}
@Override
public Object getChild(int groupPosition, int childPosition) {
// TODO Auto-generated method stub
return helper.getHashList().getChild(groupPosition, childPosition);
}
@Override
public long getGroupId(int groupPosition) {
// TODO Auto-generated method stub
return groupPosition;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
// TODO Auto-generated method stub
return childPosition;
}
不难发现他们几乎都调用了
helper.getHashList()这个函数,那是因为数据源都封装在了HashList这个类里边,现在我们只需要知道调用了相关函数就会返回对应的值就可以了.