天天看點

Android RecyclerView 使用完全解析 體驗藝術般的控件

recyclerview出現已經有一段時間了,相信大家肯定不陌生了,大家可以通過導入support-v7對其進行使用。 

據官方的介紹,該控件用于在有限的視窗中展示大量資料集,其實這樣功能的控件我們并不陌生,例如:listview、gridview。

那麼有了listview、gridview為什麼還需要recyclerview這樣的控件呢?整體上看recyclerview架構,提供了一種插拔式的體驗,高度的解耦,異常的靈活,通過設定它提供的不同layoutmanager,itemdecoration , itemanimator實作令人瞠目的效果。

你想要控制其顯示的方式,請通過布局管理器layoutmanager

你想要控制item間的間隔(可繪制),請通過itemdecoration

你想要控制item增删的動畫,請通過itemanimator

你想要控制點選、長按事件,請自己寫(擦,這點尼瑪。)

鑒于我們對于listview的使用特别的熟悉,對比下recyclerview的使用代碼:

ok,相比較于listview的代碼,listview可能隻需要去設定一個adapter就能正常使用了。而recyclerview基本需要上面一系列的步驟,那麼為什麼會添加這麼多的步驟呢?

那麼就必須解釋下recyclerview的這個名字了,從它類名上看,recyclerview代表的意義是,我隻管recycler view,也就是說recyclerview隻管回收與複用view,其他的你可以自己去設定。可以看出其高度的解耦,給予你充分的定制自由(是以你才可以輕松的通過這個控件實作listview,girdview,瀑布流等效果)。

activity

activity的布局檔案

item的布局檔案

這麼看起來用法與listview的代碼基本一緻哈~~ 

看下效果圖:

Android RecyclerView 使用完全解析 體驗藝術般的控件

看起來好醜,item間應該有個分割線,當你去找時,你會發現recyclerview并沒有支援divider這樣的屬性。那麼怎麼辦,你可以給item的布局去設定margin,當然了這種方式不夠優雅,我們文章開始說了,我們可以自由的去定制它,當然我們的分割線也是可以定制的。

我們可以通過該方法添加分割線: 

<code>mrecyclerview.additemdecoration()</code> 

該方法的參數為recyclerview.itemdecoration,該類為抽象類,官方目前并沒有提供預設的實作類(我覺得最好能提供幾個)。 

該類的源碼:

當我們調用<code>mrecyclerview.additemdecoration()</code>方法添加decoration的時候,recyclerview在繪制的時候,去會繪制decorator,即調用該類的ondraw和ondrawover方法,

ondraw方法先于drawchildren

ondrawover在drawchildren之後,一般我們選擇複寫其中一個即可。

getitemoffsets 可以通過outrect.set()為每個item設定一定的偏移量,主要用于繪制decorator。

接下來我們看一個<code>recyclerview.itemdecoration</code>的實作類,該類很好的實作了recyclerview添加分割線(當使用layoutmanager為linearlayoutmanager時)。 

擷取到listdivider以後,該屬性的值是個drawable,在<code>getitemoffsets</code>中,outrect去設定了繪制的範圍。ondraw中實作了真正的繪制。

我們在原來的代碼中添加一句:

ok,現在再運作,就可以看到分割線的效果了。

Android RecyclerView 使用完全解析 體驗藝術般的控件

該分割線是系統預設的,你可以在theme.xml中找到該屬性的使用情況。那麼,使用系統的listdivider有什麼好處呢?就是友善我們去随意的改變,該屬性我們可以直接聲明在:

然後自己寫個drawable即可,下面我們換一種分隔符:

現在的樣子是:

Android RecyclerView 使用完全解析 體驗藝術般的控件

當然了,你可以根據自己的需求,去随意的繪制,反正是畫出來的,随便玩~~

ok,看到這,你可能覺得,這玩意真尼瑪麻煩,完全不能比拟的心愛的listview。那麼繼續看。

好了,上面實作了類似listview樣子的demo,通過使用其預設的linearlayoutmanager。

recyclerview.layoutmanager吧,這是一個抽象類,好在系統提供了3個實作類:

linearlayoutmanager 現行管理器,支援橫向、縱向。

gridlayoutmanager 網格布局管理器

staggeredgridlayoutmanager 瀑布就式布局管理器

上面我們已經初步體驗了下linearlayoutmanager,接下來看gridlayoutmanager。

gridlayoutmanager

我們嘗試去實作類似gridview,秒秒鐘的事情:

隻需要修改layoutmanager即可,還是很nice的。

當然了,改為gridlayoutmanager以後,對于分割線,前面的divideritemdecoration就不适用了,主要是因為它在繪制的時候,比如水準線,針對每個child的取值為:

因為每個item一行,這樣是沒問題的。而gridlayoutmanager時,一行有多個childitem,這樣就多次繪制了,并且gridlayoutmanager時,item如果為最後一列(則右邊無間隔線)或者為最後一行(底部無分割線)。

針對上述,我們編寫了<code>dividergriditemdecoration</code>。

主要在<code>getitemoffsets</code>方法中,去判斷如果是最後一行,則不需要繪制底部;如果是最後一列,則不需要繪制右邊,整個判斷也考慮到了<code>staggeredgridlayoutmanager</code>的橫向和縱向,是以稍稍有些複雜。最重要還是去了解,如何繪制什麼的不重要。一般如果僅僅是希望有空隙,還是去設定item的margin友善。

最後的效果是:

Android RecyclerView 使用完全解析 體驗藝術般的控件

ok,看到這,你可能還覺得recyclerview不夠強大?

但是如果我們有這麼個需求,縱屏的時候顯示為listview,橫屏的時候顯示兩列的gridview,我們recyclerview可以輕松搞定,而如果使用listview去實作還是需要點功夫的~~~

當然了,這隻是皮毛,下面讓你心服口服。

staggeredgridlayoutmanager

瀑布流式的布局,其實他可以實作<code>gridlayoutmanager</code>一樣的功能,僅僅按照下列代碼:

這兩種寫法顯示的效果是一緻的,但是注意staggeredgridlayoutmanager構造的第二個參數傳一個orientation,如果傳入的是<code>staggeredgridlayoutmanager.vertical</code>代表有多少列;那麼傳入的如果是<code>staggeredgridlayoutmanager.horizontal</code>就代表有多少行,比如本例如果改為:

那麼效果為:

Android RecyclerView 使用完全解析 體驗藝術般的控件

可以看到,固定為4行,變成了左右滑動。有一點需要注意,如果是橫向的時候,item的寬度需要注意去設定,畢竟橫向的寬度沒有限制了,應為控件可以橫向滾動了。 

如果你需要一樣橫向滾動的gridview,那麼恭喜你。

ok,接下來準備看大招,如果讓你去實作個瀑布流,最起碼不是那麼随意就可以實作的吧?但是,如果使用recyclerview,分分鐘的事。 

那麼如何實作?其實你什麼都不用做,隻要使用<code>staggeredgridlayoutmanager</code>我們就已經實作了,隻是上面的item布局我們使用了固定的高度,下面我們僅僅在擴充卡的<code>onbindviewholder</code>方法中為我們的item設定個随機的高度(代碼就不貼了,最後會給出源碼下載下傳位址),看看效果圖:

Android RecyclerView 使用完全解析 體驗藝術般的控件

是不是棒棒哒,通過recyclerview去實作listview、gridview、瀑布流的效果基本上沒有什麼差別,而且可以僅僅通過設定不同的layoutmanager即可實作。

還有更nice的地方,就在于item增加、删除的動畫也是可配置的。接下來看一下itemanimator。

itemanimator也是一個抽象類,好在系統為我們提供了一種預設的實作類,期待系統多 

添加些預設的實作。

借助預設的實作,當item添加和移除的時候,添加動畫效果很簡單:

系統為我們提供了一個預設的實作,我們為我們的瀑布流添加以上一行代碼,效果為:

Android RecyclerView 使用完全解析 體驗藝術般的控件

如果是gridlayoutmanager呢?動畫效果為:

Android RecyclerView 使用完全解析 體驗藝術般的控件

注意,這裡更新資料集不是用<code>adapter.notifydatasetchanged()</code>而是 

<code>notifyiteminserted(position)</code>與<code>notifyitemremoved(position)</code> 

否則沒有動畫效果。 

上述為adapter中添加了兩個方法:

activity中點選menuitem觸發:

好了,到這我對這個控件已經不是一般的喜歡了~~~

當然了隻提供了一種動畫,那麼我們肯定可以去自定義各種nice的動畫效果。 

提供了<code>slideinoutleftitemanimator</code>,<code>slideinoutrightitemanimator</code>, 

<code>slideinouttopitemanimator</code>,<code>slideinoutbottomitemanimator</code>等動畫效果。

不過一個挺郁悶的地方就是,系統沒有提供clicklistener和longclicklistener。 

不過我們也可以自己去添加,隻是會多了些代碼而已。 

實作的方式比較多,你可以通過mrecyclerview.addonitemtouchlistener去監聽然後去判斷手勢, 

當然你也可以通過adapter中自己去提供回調,這裡我們選擇後者,前者的方式,大家有興趣自己去實作。

那麼代碼也比較簡單:

adapter中自己定義了個接口,然後在onbindviewholder中去為holder.itemview去設定相應 

的監聽最後回調我們設定的監聽。

最後别忘了給item添加一個drawable:

activity中去設定監聽:

測試效果:

Android RecyclerView 使用完全解析 體驗藝術般的控件

ok,到此我們基本介紹了recylerview常見用法,包含了:

系統提供了幾種layoutmanager的使用;

如何通過自定義itemdecoration去設定分割線,或者一些你想作為分隔的drawable,注意這裡 

巧妙的使用了系統的listdivider屬性,你可以嘗試添加使用divider和dividerheight屬性。

如何使用itemanimator為recylerview去添加item移除、添加的動畫效果。

介紹了如何添加itemclicklistener與itemlongclicklistener。

可以看到recyclerview可以實作:

listview的功能

gridview的功能

橫向scrollview的功能

瀑布流效果

便于添加item增加和移除動畫

整個體驗下來,感覺這種插拔式的設計太棒了,如果系統再能提供一些常用的分隔符,多添加些動畫效果就更好了。

通過簡單改變下layoutmanager,就可以産生不同的效果,那麼我們可以根據手機螢幕的寬度去動态設定layoutmanager,螢幕寬度一般的,顯示為listview;寬度稍大的顯示兩列的gridview或者瀑布流(或者橫縱螢幕切換時變化,有點意思~);顯示的列數和寬度成正比。甚至某些特殊螢幕,讓其橫向滑動~~再選擇一個nice的動畫效果,相信這種插件式的編碼體驗一定會讓你迅速愛上recyclerview。

<a target="_blank" href="http://blog.csdn.net/lmj623565791/article/details/38173061">android 自定義recyclerview 實作真正的gallery效果</a>

<a target="_blank" href="https://www.grokkingandroid.com/first-glance-androids-recyclerview/">a first glance at android’s recyclerview</a>

<a target="_blank" href="https://github.com/gabrielemariotti/recyclerviewitemanimators">https://github.com/gabrielemariotti/recyclerviewitemanimators</a>

<a target="_blank" href="https://gist.github.com/alexfu/0f464fc3742f134ccd1e">divideritemdecoration</a>

繼續閱讀