1适配器实现SectionIndexer接口
@Override
public Object[] getSections() {
return new Object[0];
}
//此方法是通过字母的Ascii码,与集合里的元素拼音的首字母的Ascii码做比较,返回第一个相同的索引位置(即分组位置)
@Override
public int getPositionForSection(int sectionIndex) {
for (int i = 0; i < friends.size(); i++) {
if (sectionIndex == friends.get(i).pinyin.toUpperCase().charAt(0)) {
return i;
}
}
return 0;
}
//此方法是通过索引位置,获取到此索引所属的分组字母
@Override
public int getSectionForPosition(int position) {
return friends.get(position).pinyin.toUpperCase().charAt(0);
}
2在XML文件里放置一个伪item,遮挡住listview的第一个item,它用来做碰撞位移
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
>
<ListView
android:id="@+id/listview_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
<LinearLayout
android:id="@+id/title_layout"
android:layout_width="fill_parent"
android:layout_height="30dp"
android:layout_gravity="right|top"
android:background="#ff303030"
android:orientation="vertical" >
<TextView
android:id="@+id/title_layout_catalog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="22sp"
android:textColor="@android:color/white"
android:background="@android:color/holo_green_light"
android:gravity="center"
/>
</LinearLayout>
<com.explam.slidelayoutdemo.QuickIndexBar
android:id="@+id/quick_index"
android:background="#f00"
android:layout_width="30dp"
android:layout_height="match_parent"
android:layout_alignParentRight="true"/>
<TextView
android:id="@+id/tv_letter"
android:visibility="invisible"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/quick_index"
/>
</RelativeLayout>
3在代码里设置listview的滚动监听,通过firstVisibleItem去判断所属分类,当(firstVisibleItem + 1 == nextSectionPosition)第一个可见条目的下一个item与判断出来的下一个分类的位置相同的时候,就要开始进行碰撞效果实现
//设置滚动监听,去实现挤压效果
mLv_main.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
//通过第一个可见条目索引拿到这个位置的Ascii码,即字母A的Ascii码
int section = adapter.getSectionForPosition(firstVisibleItem);
//获取第二个可见条目位置的Ascii码,可能是A,也可能是其他
int nextSection = adapter.getSectionForPosition(firstVisibleItem + 1);
//通过第二个可见条目的Ascci码,拿到它的字母的位置
int nextSectionPosition = adapter.getPositionForSection(nextSection);
System.out.println("next:"+(+nextSection));
float titleY = view.getY();//获取listview在容器里的Y坐标(其实就是0)
//如果上次记录的可见条目索引不等于现在的滚动到的可见条目索引
if (lastVisibleIndex != firstVisibleItem) {
//就将固定在顶部的伪item布局的文本设置为当前可见条目的分类名
mTitle.setText((char) section + "");
}
//如果当前可见条目的下一个条目就是下一个分组字母的位置
if (firstVisibleItem + 1 == nextSectionPosition) {
View firstView = view.getChildAt(0);//获取listview当前显示的第一个孩子
int bottom = firstView.getBottom();//得到第一个孩子当前的底部bottom
int titleLayoutHeight = titleLayout.getHeight();
//如果bottom小于伪item的容器高度,说明要开始进行挤压碰撞了
if (bottom < titleLayoutHeight) {
//求出差值,即需要设置给伪容器的y坐标,实现碰撞效果
titleY = bottom - titleLayoutHeight;
}
}
//未满足上面的条件,就将伪容器的y坐标设置的和listview一样,满足了就设置计算的值
titleLayout.setY(titleY);
lastVisibleIndex = firstVisibleItem;
}
});