PinnedSectionListView:分組的listView滑動中固定組標題的實現
在很多應用中,看到這樣的listview:listview滑動過程中分組標題固定在上方,當第二個組滑上來時,第一個組才跟著上滑,下一個組固定,直到該組也滑出上邊緣。世上無難事只怕有心人,在github上就有人做出來了,而且效果很好(后來發現安卓自帶應用中聯系人應用就是這樣的,估計github的作者也是仿照著聯系人做出來的吧)。
先看截圖:

PinnedSectionListView繼承自listview,眾所周知listview的每個子view都是按順序跟著滾動的,要實現聯系人listview的效果還真的找不到思路。看了PinnedSectionListView之后,感覺要改造一個現有的控件,一般都是通過重繪子view來實現的。ViewGroup(ListView繼承自它)重繪子view的方法是dispatchDraw。
看看PinnedSectionListView在dispatchDraw中有那些特別的處理:
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (mPinnedSection != null) {
// prepare variables
int pLeft = getListPaddingLeft();
int pTop = getListPaddingTop();
View view = mPinnedSection.view;
// draw child
canvas.save();
int clipHeight = view.getHeight() +
(mShadowDrawable == null ? 0 : Math.min(mShadowHeight, mSectionsDistanceY));
canvas.clipRect(pLeft, pTop, pLeft + view.getWidth(), pTop + clipHeight);
canvas.translate(pLeft, pTop + mTranslateY);
drawChild(canvas, mPinnedSection.view, getDrawingTime());
if (mShadowDrawable != null && mSectionsDistanceY > 0) {
mShadowDrawable.setBounds(mPinnedSection.view.getLeft(),
mPinnedSection.view.getBottom(),
mPinnedSection.view.getRight(),
mPinnedSection.view.getBottom() + mShadowHeight);
mShadowDrawable.draw(canvas);
}
canvas.restore();
}
} 關鍵在于canvas.translate(pLeft, pTop + mTranslateY);意思是在繪制mPinnedSection的時候,listview滑動了多長的距離,就將canvas移動多少的距離,使mPinnedSection始終在可見的范圍內固定不變。
使用方法:
1.在xml布局文件中將ListView替換成PinnedSectionListView
<com.hb.views.PinnedSectionListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/> 2.讓你的ListAdapter繼承PinnedSectionListAdapter接口,最簡單的做法是只增加isItemViewTypePinned方法,該方法必須在item為pinned的情況下返回true。
// Our adapter class implements 'PinnedSectionListAdapter' interface
class MyPinnedSectionListAdapter extends BaseAdapter implements PinnedSectionListAdapter {
...
// We implement this method to return 'true' for all view types we want to pin
@Override
public boolean isItemViewTypePinned(int viewType) {
return viewType == <type to be pinned>;
}
} 項目地址:https://github.com/beworker/pinned-section-listview