项目用到通讯录列表,百度找到PinnedHeaderListView,但是用起来发现还有几个bug例如空组时抬头显示错误等等,接入也比较麻烦需要重新很多方法内部处理算法也没完全封装起来,所以就自己修复了下里面的bug并封装了代码,现在只需要重写一个adapter就能实现通讯录效果。
package com.test.view;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import java.util.ArrayList;
import java.util.List;
public abstract class PinnedHeaderAdapter<T> extends BaseAdapter {
private HeadSectionIndexer mIndexer;
private String sections;
private List<T> lists;
public PinnedHeaderAdapter(List<T> lists, String sections) {
this.sections = sections;
this.lists = lists;
notifyDataSetChanged();
}
@Override
public void notifyDataSetChanged() {
int[] counts = new int[sections.length()];
List<T> temp = new ArrayList<>();
for(T t : lists) {
int index = getIndex(sections, t);
int listIndex = 0;
//计算所在组的最末位置,并插入列表
for(int i = 0; i <= index; i++) {
listIndex += counts[i];
}
temp.add(listIndex, t);
//增加组成员个数
counts[index]++;
}
lists.clear();
lists.addAll(temp);
mIndexer = new HeadSectionIndexer(sections, counts);
super.notifyDataSetChanged();
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
int section = mIndexer.getSectionForPosition(i);
if(mIndexer.getPositionForSection(section) == i) {
return getView(i, view, true, mIndexer.getSection(i));
} else {
return getView(i, view, false, null);
}
}
/**
* Pinned header state: don't show the header.
*/
public static final int PINNED_HEADER_GONE = 0;
/**
* Pinned header state: show the header at the top of the list.
*/
public static final int PINNED_HEADER_VISIBLE = 1;
/**
* Pinned header state: show the header. If the header extends beyond
* the bottom of the first shown element, push it up and clip.
*/
public static final int PINNED_HEADER_PUSHED_UP = 2;
public int getPinnedHeaderState(int position) {
int realPosition = position;
if(realPosition < 0) {
return PINNED_HEADER_GONE;
}
int section = mIndexer.getSectionForPosition(realPosition);
int nextSectionPosition = mIndexer.getPositionForSection(section + 1);
if(nextSectionPosition != -1 && realPosition == nextSectionPosition - 1) {
return PINNED_HEADER_PUSHED_UP;
}
return PINNED_HEADER_VISIBLE;
}
public HeadSectionIndexer getIndexer() {
return mIndexer;
}
public abstract void configurePinnedHeader(View header, int position, int alpha, String section);
public abstract View getHeaderView(ViewGroup viewGroup);
/**
* 返回t在sections中要指定的位置
*/
public abstract int getIndex(String sections, T t);
public abstract View getView(int i, View view, boolean headerShow, String title);
}
继承adapter主要是实现getIndex方法,返回Int值表示数据t要插入sections中的位置,比如 sections为ABCDEFGHIJKLMNOPQRSTUVWXYZ#,t为字符串a则返回0,t为1则插入未知组#返回#的位置即可