github地址:https://github.com/JimiSmith/PinnedHeaderListView
关于实现类似联系人列表,组的头部总是悬浮在listview最顶部的效果,github上面有两个比较好的实现,分别是pinnedSectionListview和pinnedHeaderListView,之所以选择后者进行源码解析,是因为后者的源码比较简单,便于我们理解实现的精髓所在。
如果你想直接实现Android仿联系人列表分组悬浮列表,
自定义PinnedHeaderListView,看这里 http://blog.csdn.net/u010335298/article/details/51150346
代码结构
翻开源码,我们一共可以找到四个有用的类,分别是:
1. PinnedHeaderListView: 实现组的头部总是悬浮在顶部的listview
2. SectionedBaseAdapter: 封装的adapter的抽象类
3. PinnedHeaderListViewMainActivity: 具体使用的activity
4. TestSectionedAdapter: 实现了抽象类SectionedBaseAdapter的adapter
SectionedBaseAdapter
首先,我们来看抽象类SectionedBaseAdapter的实现
接口PinnedHeaderListView.PinnedSectionedHeaderAdapter
public abstract class SectionedBaseAdapter extends BaseAdapter implements PinnedHeaderListView.PinnedSectionedHeaderAdapter
可以看到,SectionedBaseAdapter继承BaseAdapter,
同时实现了PinnedHeaderListView.PinnedSectionedHeaderAdapter这个接口
我们来看PinnedHeaderListView.PinnedSectionedHeaderAdapter的定义:
public static interface PinnedSectionedHeaderAdapter {
public boolean isSectionHeader(int position); //是否是组的头部
public int getSectionForPosition(int position); //根据位置判断对应的组号
public View getSectionHeaderView(int section, View convertView, ViewGroup parent); // 得到组的头部view
public int getSectionHeaderViewType(int section); //
public int getCount();
}
看一下SectionedBaseAdapter的实现:
/*********************************************************************************************************
*
*
* 以下 , 实现了PinnedSectionedHeaderAdapter接口
*
*
* *********************************************************************************************************/
/**
* 是否是组的头部
* @param position
* @return
*/
public final boolean isSectionHeader(int position) {
int sectionStart = 0;
for (int i = 0; i < internalGetSectionCount(); i++) {
if (position == sectionStart) {
return true;
} else if (position < sectionStart) {
return false;
}
sectionStart += internalGetCountForSection(i) + 1;
}
return false;
}
/**
* 根据位置得到对应的组号
* @param position
* @return
*/
public final int getSectionForPosition(int position) {
// first try to retrieve values from cache
Integer cachedSection = mSectionCache.get(position);
if (cachedSection != null) {
return cachedSection;
}
int sectionStart = 0;
for (int i = 0; i < internalGetSectionCount(); i++) {
int sectionCount = internalGetCountForSection(i);
int sectionEnd = sectionStart + sectionCount + 1;
if (position >= sectionStart && position < sectionEnd) {
mSectionCache.put(position, i);
return i;
}
sectionStart = sectionEnd;
}
return 0;
}
/**
*
* @param section
* @param convertView
* @param parent
* @return
*/
public abstract View getSectionHeaderView(int section, View convertView, ViewGroup parent);
/**
*
* @param section
* @return
*/