1. 效果, 即是C D 等等的字母分组。
2.实现
在ContactListActivity.java 中的
private final class ContactItemListAdapter extends CursorAdapter
implements SectionIndexer, OnScrollListener, PinnedHeaderListView.PinnedHeaderAdapter
主要实现。 此类中有一个开关,用于打开和关闭 SectionHeaders的显示。
private boolean mDisplaySectionHeaders = true;
在其getView()方法中,有调用方法bindSectionHeader()用于处理SectionHeader的显示。
private void bindSectionHeader(View itemView, int position, boolean displaySectionHeaders) {
final ContactListItemView view = (ContactListItemView)itemView;
final ContactListItemCache cache = (ContactListItemCache) view.getTag();
if (!displaySectionHeaders) {
view.setSectionHeader(null);
view.setDividerVisible(true);
} else {
final int section = getSectionForPosition(position);
if (getPositionForSection(section) == position) {
String title = (String)mIndexer.getSections()[section];
view.setSectionHeader(title);
} else {
view.setDividerVisible(false);
view.setSectionHeader(null);
}
// move the divider for the last item in a section
if (getPositionForSection(section + 1) - 1 == position) {
view.setDividerVisible(false);
} else {
view.setDividerVisible(true);
}
}
}
ContactListItemView 是一个包含有SectionHeader的view, 可以设置其显示与不显示。通过判断目前位置是否为此SectionHeader纪录的第一条纪录, 如果是则显示SectionHeader, 如果不是则不显示。
分组的主要实现通过下面这个类。
public class ContactsSectionIndexer implements SectionIndexer;
//构造函数如下
public ContactsSectionIndexer(String[] sections, int[] counts) {
if (sections == null || counts == null) {
throw new NullPointerException();
}
if (sections.length != counts.length) {
throw new IllegalArgumentException(
"The sections and counts arrays must have the same length");
}
// TODO process sections/counts based on current locale and/or specific section titles
this.mSections = sections;
mPositions = new int[counts.length];
int position = 0;
for (int i = 0; i < counts.length; i++) {
if (mSections[i] == null) {
mSections[i] = " ";
} else {
mSections[i] = mSections[i].trim();
}
Log.e("Contact", "mSections["+i+"] is :"+mSections[i]);
mPositions[i] = position;
position += counts[i];
}
mCount = position;
}
传入的参数
String[] sections : 是从数据库获取到的存在的首字母的数组。
int[] counts: 为每个首字母分组下的纪录条目。
public int getPositionForSection(int section) {
if (section < 0 || section >= mSections.length) {
return -1;
}
return mPositions[section];
}
public int getSectionForPosition(int position) {
if (position < 0 || position >= mCount) {
return -1;
}
int index = Arrays.binarySearch(mPositions, position);
/*
* Consider this example: section positions are 0, 3, 5; the supplied
* position is 4. The section corresponding to position 4 starts at
* position 3, so the expected return value is 1. Binary search will not
* find 4 in the array and thus will return -insertPosition-1, i.e. -3.
* To get from that number to the expected value of 1 we need to negate
* and subtract 2.
*/
return index >= 0 ? index : -index - 2;
}
mPositions 存储的是 每个sectionHeader 的开始位置。
如A:3个, B:2个 C:4个。那么其mPositions[0] =0 ,mPositions[1]=3, mPositions[2] = 5.
getSectionForPosition,通过你给出的位置去判断此条纪录属于哪个sectionHeader的。里面使用到得binarySearch说明:假设要查找的 position为4 ,那它应该是属于mPosition[1]的Header。 但是Binary search 它不会找到4这个数字,所以 在3 和5之间, 他需要返回:插入的-(insertPosition = 2)-1 的值也就是-3。 我们要转化为为我们需要获取的正确的section 的值 就应该使用 - index -2 得到。