RecyclerView設(shè)置間距和添加分割線(xiàn)的方法
使用RecyclerView布局,經(jīng)常需要調(diào)整間距和添加分割線(xiàn)以達(dá)到更美觀(guān)的效果,雖然一直接觸和使用,但卻從來(lái)沒(méi)有認(rèn)真研究過(guò),經(jīng)常忘記如何使用,現(xiàn)在就來(lái)好好研究一番
先放上一個(gè)沒(méi)有分割線(xiàn)的效果圖
添加默認(rèn)的分割線(xiàn)
使用RecyclerView.addItemDecoration(ItemDecoration decor)
方法,添加默認(rèn)的分割線(xiàn)
最簡(jiǎn)單的方式就是,添加一個(gè)簡(jiǎn)單的DividerItemDecoration
類(lèi):
//添加默認(rèn)的分割線(xiàn) recyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL));
得到的效果圖
另外,可以使用DividerItemDecoration.setDrawble()
傳入一個(gè)Drawable對(duì)象來(lái)定義我們想要的效果
繪制一個(gè)高度為2dp,顏色為綠色的矩形并將它傳入
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> ? ? <solid android:color="#00ff00"/> ? ? <size android:height="2dp" /> </shape>
//添加默認(rèn)分割線(xiàn) DividerItemDecoration decoration = new DividerItemDecoration(this,DividerItemDecoration.VERTICAL); decoration.setDrawable(getResources().getDrawable(R.drawable.divider_green)); recyclerView.addItemDecoration(decoration);
得到的效果圖
然后,我發(fā)現(xiàn)RecyclerView添加分割線(xiàn)還有一個(gè)重載方法:
RecyclerView.addItemDecoration(ItemDecoration decor, int index)
想也沒(méi)想,還以為是在指定的位置添加分割線(xiàn),隨便打了個(gè)數(shù)字測(cè)試,結(jié)果程序閃退了
翻開(kāi)源碼一看,原來(lái)內(nèi)部用了一個(gè)數(shù)組存儲(chǔ)添加進(jìn)來(lái)的ItemDecoration,怪不得方法名是addItemDecoration()而不是setItemDecoration(),也就是說(shuō)RecyclerView可以添加多個(gè)ItemDecoration,那么就來(lái)試試吧:
繪制了三個(gè)矩形,顏色分別為綠色、紅色和藍(lán)色,高度分別為4dp、8dp和12dp,將它們都傳入
//添加默認(rèn)分割線(xiàn) DividerItemDecoration decoration1 = new DividerItemDecoration(this,DividerItemDecoration.VERTICAL); decoration1.setDrawable(getResources().getDrawable(R.drawable.divider_green)); DividerItemDecoration decoration2 = new DividerItemDecoration(this,DividerItemDecoration.VERTICAL); decoration2.setDrawable(getResources().getDrawable(R.drawable.divider_red)); DividerItemDecoration decoration3 = new DividerItemDecoration(this,DividerItemDecoration.VERTICAL); decoration3.setDrawable(getResources().getDrawable(R.drawable.divider_blue));
recyclerView.addItemDecoration(decoration1); recyclerView.addItemDecoration(decoration2); recyclerView.addItemDecoration(decoration3);
效果圖:
換個(gè)順序傳入
recyclerView.addItemDecoration(decoration3); recyclerView.addItemDecoration(decoration2); recyclerView.addItemDecoration(decoration1);
效果圖:
很顯然,繪制順序是以?xún)?nèi)部數(shù)組中的存儲(chǔ)順序?yàn)榛鶞?zhǔn)的,并且間距是由所有傳入的ItemDecoration的高度或?qū)挾裙餐?jì)算得到的(所以會(huì)出現(xiàn)除了三種顏色外的灰色分割線(xiàn))
添加自定義分割線(xiàn)
默認(rèn)的分割線(xiàn)效果不好,想要自定義分割線(xiàn)該怎么做?
很簡(jiǎn)單,我們只需要自定義一個(gè)類(lèi)去繼承ItemDecoration類(lèi),并重寫(xiě)相關(guān)的方法就可以了。添加默認(rèn)分割線(xiàn)時(shí)使用的DividerItemDecoration也是如此。
編寫(xiě)一個(gè)MyDecoration類(lèi),繼承RecyclerView.ItemDecoration類(lèi),Ctrl+O,發(fā)現(xiàn)除去已棄用的方法和構(gòu)造方法,ItemDecoration類(lèi)主要有三個(gè)方法:
public void onDraw(Canvas c, RecyclerView parent, State state) public void onDrawOver(Canvas c, RecyclerView parent, State state) public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state)
大概描述一下幾個(gè)方法的作用:
- getItemOffsets(),獲取Item的偏移量,調(diào)整參數(shù)中outRect的相關(guān)值,可以實(shí)現(xiàn)類(lèi)似padding的效果。
- onDraw(),用這種方法繪制的任何內(nèi)容都將在繪制項(xiàng)目視圖之前繪制,繪圖的內(nèi)容將出現(xiàn)在視圖下方。
- onDrawOver(),用這種方法繪制的任何內(nèi)容都將在繪制項(xiàng)目視圖之后繪制,繪圖的內(nèi)容會(huì)出現(xiàn)在視圖上方。
百聞不如一見(jiàn),直接看實(shí)際效果
getItemOffsets()方法:
//添加自定義分割線(xiàn) class MyDecoration extends RecyclerView.ItemDecoration { ?? ?@Override ?? ?public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { ?? ??? ?super.getItemOffsets(outRect, view, parent, state); ?? ??? ?//設(shè)置間距 ?? ??? ?outRect.bottom = 10; ?? ?} } //添加裝飾 recyclerView.addItemDecoration(new MyDecoration());
這里僅設(shè)置了底部間距,實(shí)現(xiàn)的效果類(lèi)似之前使用的DividerItemDecoration
再給每個(gè)方向上都設(shè)置間距,看看效果
//添加自定義分割線(xiàn) class MyDecoration extends RecyclerView.ItemDecoration { ?? ?@Override ?? ?public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { ?? ??? ?super.getItemOffsets(outRect, view, parent, state); ?? ??? ?//設(shè)置間距 ?? ??? ?outRect.left = 30; ? ? ? ? outRect.right = 50; ? ? ? ? outRect.top = 15; ? ? ? ? outRect.bottom = 10; ?? ?} } //添加裝飾 recyclerView.addItemDecoration(new MyDecoration());
可以看到,實(shí)現(xiàn)了類(lèi)似padding的效果
onDraw()方法:
//添加自定義分割線(xiàn) class MyDecoration extends RecyclerView.ItemDecoration { ?? ?@Override ?? ?public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { ?? ??? ?super.getItemOffsets(outRect, view, parent, state); ?? ??? ?//設(shè)置間距 ? ? ? ? outRect.bottom = 10; ? ? } ? ?? ?? ?@Override ?? ?public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { ? ? ?? ?super.onDraw(c, parent, state); ? ? ? ? Paint paint = new Paint(); ? ? ? ? paint.setColor(Color.BLUE); ?? ??? ?//獲取item的數(shù)量 ? ? ? ? int count = parent.getChildCount(); ? ? ? ? //設(shè)置要繪制的矩形的left、right、top、bottom值 ? ? ? ? int left = parent.getPaddingLeft(); ? ? ? ? int right = parent.getWidth() - parent.getPaddingRight(); ? ? ? ? for (int i = 0; i < count; i++){ ? ? ? ? ?? ?//獲取對(duì)應(yīng)的item ?? ? ? ? ? ?View view = parent.getChildAt(i); ?? ? ? ? ? ?float top = view.getBottom(); ?? ? ? ? ? ?float bottom = view.getBottom() + 10; ?? ? ? ? ? ?//繪制矩形 ?? ? ? ? ? ?c.drawRect(left,top,right,bottom,paint); ? ? ?? ?} ?? ?} } recyclerView.addItemDecoration(new MyDecoration());
這里仍?xún)H設(shè)置底部間距,并在onDraw()方法中實(shí)例化一個(gè)paint對(duì)象,設(shè)置顏色為藍(lán)色,用于最終的繪制。之后獲取item的數(shù)量,通過(guò)一個(gè)循環(huán)來(lái)繪制每一個(gè)item下方的分割線(xiàn)(當(dāng)然也可以通過(guò)某些條件判斷,以達(dá)到只繪制部分分割線(xiàn)的效果),這個(gè)分割線(xiàn)的頂部恰好是item的底部,分割線(xiàn)的底部則是item的底部+間距,所以有:
float top = view.getBottom(); float bottom = view.getBottom() + 10; //繪制矩形 c.drawRect(left,top,right,bottom,paint);
實(shí)際效果圖:
onDrawOver()方法:
直接在剛才的基礎(chǔ)上,重寫(xiě)onDrawOver()方法
@Override public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { ?? ?super.onDrawOver(c, parent, state); ? ? Paint paint = new Paint(); ? ? paint.setColor(Color.RED); ? ? int count = parent.getChildCount(); ? ? float left = parent.getRight() - 40; ? ? float right = parent.getRight(); ? ? for (int i = 0; i < count; i++){ ?? ? ? ?View view = parent.getChildAt(i); ?? ? ? ?float top = view.getTop(); ?? ? ? ?//會(huì)覆蓋掉部分藍(lán)色分割線(xiàn) ?? ? ? ?float bottom = view.getBottom() + 5; ?? ? ? ?c.drawRect(left,top,right,bottom,paint); ?? ?} }
之前說(shuō)過(guò),onDraw()方法繪圖的內(nèi)容將出現(xiàn)在視圖下方,而onDrawOver()方法的繪圖內(nèi)容會(huì)出現(xiàn)在視圖上方,因此這里的紅色分割線(xiàn)會(huì)略微覆蓋掉一部分之前的藍(lán)色分割線(xiàn)
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
android webview 中l(wèi)ocalStorage無(wú)效的解決方法
這篇文章主要介紹了android webview 中l(wèi)ocalStorage無(wú)效的解決方法,本文直接給出解決方法實(shí)現(xiàn)代碼,需要的朋友可以參考下2015-06-06Android使用popupWindow仿微信彈出框使用方法
這篇文章主要為大家詳細(xì)介紹了Android使用popupWindow仿微信彈出框使用方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-09-09android內(nèi)存優(yōu)化之圖片優(yōu)化
對(duì)圖片本身進(jìn)行操作。盡量不要使用setImageBitmap、setImageResource、BitmapFactory.decodeResource來(lái)設(shè)置一張大圖,因?yàn)檫@些方法在完成decode后,最終都是通過(guò)java層的createBitmap來(lái)完成的,需要消耗更多內(nèi)存2012-12-12Android實(shí)現(xiàn)Back功能代碼片段總結(jié)
今天把在公司實(shí)現(xiàn)某功能所用到的Back鍵功能模塊代碼片段做一個(gè)整理。方便以后直接拿出來(lái)使用2014-09-09Android 使用自定義RecyclerView控件實(shí)現(xiàn)Gallery效果
這篇文章主要介紹了Android 使用自定義RecyclerView 實(shí)現(xiàn)Gallery效果,本文給大家簡(jiǎn)單介紹了RecyclerView的基本用法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-10-10Android?Compose狀態(tài)改變動(dòng)畫(huà)animateXxxAsState使用詳解
這篇文章主要為大家介紹了Android?Compose狀態(tài)改變動(dòng)畫(huà)animateXxxAsState使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11Android 中View.onDraw(Canvas canvas)的使用方法
這篇文章主要介紹了Android 中View.onDraw(Canvas canvas)的使用方法的相關(guān)資料,希望通過(guò)本文能幫助到大家,需要的朋友可以參考下2017-09-09Android二維碼開(kāi)發(fā)學(xué)習(xí)教程
這篇文章主要為大家分享了Android二維碼開(kāi)發(fā)學(xué)習(xí)教程,感興趣的小伙伴們可以參考一下2016-07-07Android Handler內(nèi)存泄漏詳解及其解決方案
在android開(kāi)發(fā)過(guò)程中,我們可能會(huì)遇到過(guò)令人奔潰的OOM異常,這篇文章主要介紹了Android Handler內(nèi)存泄漏詳解及其解決方案,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-08-08