github源码分享PinnedSectionListView:分组的listView滑动中固定组标题的实现
在很多应用中,看到这样的listview:listview滑动过程中分组标题固定在上方,当第二个组滑上来时,第一个组才跟着上滑,下一个组固定,直到该组也滑出上边缘。世上无难事只怕有心人,在github上就有人做出来了,而且效果很好(后来发现安卓自带应用中联系人应用就是这样的,估计github的作者也是仿照着联系人做出来的吧)。 先看截图: PinnedSectionListView继承自listview,众所周知listview的每个子view都是按顺序跟着滚动的,要实现联系人listview的效果还真的找不到思路。看了PinnedSectionListView之后,感觉要改造一个现有的控件,一般都是通过重绘子view来实现的。ViewGroup(ListView继承自它)重绘子view的方法是dispatchDraw。 看看PinnedSectionListView在dispatchDraw中有那些特别的处理: 1 <div class="line number2 index1 alt1"> 2 </div> <div class="line number3 index2 alt2"> 3 </div> <div class="line number4 index3 alt1"> 4 </div> <div class="line number5 index4 alt2"> 5 </div> <div class="line number6 index5 alt1"> 6 </div> <div class="line number7 index6 alt2"> 7 </div> <div class="line number8 index7 alt1"> 8 </div> <div class="line number9 index8 alt2"> 9 </div> <div class="line number10 index9 alt1"> 10 </div> <div class="line number11 index10 alt2"> 11 </div> <div class="line number12 index11 alt1"> 12 </div> <div class="line number13 index12 alt2"> 13 </div> <div class="line number14 index13 alt1"> 14 </div> <div class="line number15 index14 alt2"> 15 </div> <div class="line number16 index15 alt1"> 16 </div> <div class="line number17 index16 alt2"> 17 </div> <div class="line number18 index17 alt1"> 18 </div> <div class="line number19 index18 alt2"> 19 </div> <div class="line number20 index19 alt1"> 20 </div> <div class="line number21 index20 alt2"> 21 </div> <div class="line number22 index21 alt1"> 22 </div> <div class="line number23 index22 alt2"> 23 </div> <div class="line number24 index23 alt1"> 24 </div> <div class="line number25 index24 alt2"> 25 </div> </td> <td class="code"> <div class="container"> <div class="line number1 index0 alt2"> `@Override` </div> <div class="line number2 index1 alt1"> `protected void dispatchDraw(Canvas canvas) {` </div> <div class="line number3 index2 alt2"> ` ``super``.dispatchDraw(canvas);` </div> <div class="line number4 index3 alt1"> ` ``if` `(mPinnedSection != ``null``) {` </div> <div class="line number5 index4 alt2"> ` ``// prepare variables` </div> <div class="line number6 index5 alt1"> ` ``int pLeft = getListPaddingLeft();` </div> <div class="line number7 index6 alt2"> ` ``int pTop = getListPaddingTop();` </div> <div class="line number8 index7 alt1"> ` ``View view = mPinnedSection.view;` </div> <div class="line number9 index8 alt2"> ` ``// draw child` </div> <div class="line number10 index9 alt1"> ` ``canvas.save();` </div> <div class="line number11 index10 alt2"> ` ``int clipHeight = view.getHeight() +` </div> <div class="line number12 index11 alt1"> ` ``(mShadowDrawable == ``null` `? 0 : Math.min(mShadowHeight, mSectionsDistanceY));` </div> <div class="line number13 index12 alt2"> ` ``canvas.clipRect(pLeft, pTop, pLeft + view.getWidth(), pTop + clipHeight);` </div> <div class="line number14 index13 alt1"> ` ``canvas.translate(pLeft, pTop + mTranslateY);` </div> <div class="line number15 index14 alt2"> ` ``drawChild(canvas, mPinnedSection.view, getDrawingTime());` </div> <div class="line number16 index15 alt1"> ` ``if` `(mShadowDrawable != ``null` `&& mSectionsDistanceY > 0) {` </div> <div class="line number17 index16 alt2"> ` ``mShadowDrawable.setBounds(mPinnedSection.view.getLeft(),` </div> <div class="line number18 index17 alt1"> ` ``mPinnedSection.view.getBottom(),` </div> <div class="line number19 index18 alt2"> ` ``mPinnedSection.view.getRight(),` </div> <div class="line number20 index19 alt1"> ` ``mPinnedSection.view.getBottom() + mShadowHeight);` </div> <div class="line number21 index20 alt2"> ` ``mShadowDrawable.draw(canvas);` </div> <div class="line number22 index21 alt1"> ` ``}` </div> <div class="line number23 index22 alt2"> ` ``canvas.restore();` </div> <div class="line number24 index23 alt1"> ` ``}` </div> <div class="line number25 index24 alt2"> `}` </div> </div> </td> </tr> </table> 关键在于```canvas.translate(pLeft, pTop + mTranslateY);意思是在绘制mPinnedSection的时候,listview滑动了多长的距离,就将canvas移动多少的距离,使mPinnedSection`始终在可见的范围内固定不变。 ...