天天看點

PinnedSectionListView:分組的listView滑動中固定組标題的實作

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

先看截圖:

PinnedSectionListView:分組的listView滑動中固定組标題的實作
PinnedSectionListView:分組的listView滑動中固定組标題的實作
PinnedSectionListView:分組的listView滑動中固定組标題的實作

pinnedsectionlistview繼承自listview,衆所周知listview的每個子view都是按順序跟着滾動的,要實作聯系人listview的效果還真的找不到思路。看了pinnedsectionlistview之後,感覺要改造一個現有的控件,一般都是通過重繪子view來實作的。viewgroup(listview繼承自它)重繪子view的方法是dispatchdraw。

看看pinnedsectionlistview在dispatchdraw中有那些特别的處理:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

<code>@override</code>

<code>protected void dispatchdraw(canvas canvas) {</code>

<code>    </code><code>super</code><code>.dispatchdraw(canvas);</code>

<code>    </code><code>if</code><code>(mpinnedsection !=</code><code>null</code><code>) {</code>

<code>        </code><code>// prepare variables</code>

<code>        </code><code>int pleft = getlistpaddingleft();</code>

<code>        </code><code>int ptop = getlistpaddingtop();</code>

<code>        </code><code>view view = mpinnedsection.view;</code>

<code>        </code><code>// draw child</code>

<code>        </code><code>canvas.save();</code>

<code>        </code><code>int clipheight = view.getheight() +</code>

<code>                </code><code>(mshadowdrawable ==</code><code>null</code><code>? 0 : math.min(mshadowheight, msectionsdistancey));</code>

<code>        </code><code>canvas.cliprect(pleft, ptop, pleft + view.getwidth(), ptop + clipheight);</code>

<code>        </code><code>canvas.translate(pleft, ptop + mtranslatey);</code>

<code>        </code><code>drawchild(canvas, mpinnedsection.view, getdrawingtime());</code>

<code>        </code><code>if</code><code>(mshadowdrawable !=</code><code>null</code><code>&amp;&amp; msectionsdistancey &gt; 0) {</code>

<code>            </code><code>mshadowdrawable.setbounds(mpinnedsection.view.getleft(),</code>

<code>                    </code><code>mpinnedsection.view.getbottom(),</code>

<code>                    </code><code>mpinnedsection.view.getright(),</code>

<code>                    </code><code>mpinnedsection.view.getbottom() + mshadowheight);</code>

<code>            </code><code>mshadowdrawable.draw(canvas);</code>

<code>        </code><code>}</code>

<code>        </code><code>canvas.restore();</code>

<code>    </code><code>}</code>

<code>}</code>

關鍵在于<code></code><code>canvas.translate(pleft, ptop + mtranslatey);</code>意思是在繪制<code>mpinnedsection</code>的時候,listview滑動了多長的距離,就将canvas移動多少的距離,使<code>mpinnedsection</code>始終在可見的範圍内固定不變。

使用方法:

1.在xml布局檔案中将listview替換成pinnedsectionlistview

<code>&lt;com.hb.views.pinnedsectionlistview</code>

<code>    </code><code>android:id=</code><code>"@android:id/list"</code>

<code>    </code><code>android:layout_width=</code><code>"match_parent"</code>

<code>    </code><code>android:layout_height=</code><code>"wrap_content"</code>

<code>    </code><code>/&gt;</code>

2.讓你的listadapter繼承<code>pinnedsectionlistadapter</code>接口,最簡單的做法是隻增加<code>isitemviewtypepinned</code>方法,該方法必須在item為pinned的情況下傳回true。

<code>// our adapter class implements 'pinnedsectionlistadapter' interface</code>

<code>class mypinnedsectionlistadapter extends baseadapter implements pinnedsectionlistadapter {</code>

<code>     </code><code>...</code>

<code>     </code><code>// we implement this method to return 'true' for all view types we want to pin</code>

<code>     </code><code>@override</code>

<code>     </code><code>public boolean isitemviewtypepinned(int viewtype) {</code>

<code>         </code><code>return</code><code>viewtype == &lt;type to be pinned&gt;;</code>

<code>     </code><code>}</code>

 項目位址:https://github.com/beworker/pinned-section-listview

最後推薦一個demo:http://blog.csdn.net/anddroid_lanyan/article/details/41895631

繼續閱讀