最近開始學(xué)習(xí)RecyclerView,總結(jié)了一些我自己覺得需要關(guān)注有那么點(diǎn)實(shí)用的點(diǎn)术羔,跟大家分享一下赢赊。以備不時(shí)之需。也許你早就了解了级历。那就當(dāng)復(fù)習(xí)復(fù)習(xí)吧释移。知識在于積累,學(xué)習(xí)寥殖,總結(jié)玩讳,分享,討論嚼贡。不管大小深淺熏纯,總結(jié)才能納為己用。請笑納咯粤策。
RecyclerView.Adapter
Adapter的作用有兩個(gè):1. 填充數(shù)據(jù) 2. 給每一個(gè)Item創(chuàng)建正確的布局樟澜。
RecyclerView.Adapter
- public VH onCreateViewHolder(ViewGroup parent, int viewType) //return 一個(gè)ViewHolder對象
- public void onBindViewHolder(VH holder, int position) 通過ViewHolder給布局填充數(shù)據(jù)
- public int getItemCount() 獲取數(shù)據(jù)總數(shù)
給RecyclerView
設(shè)置分割線的方法
- 如果不需要特殊的效果,則直接給item設(shè)置margin叮盘。- 如果要比較復(fù)雜的分割線效果秩贰,則給RecyclerView設(shè)置itemDecoration
RecyclerView的點(diǎn)擊事件
RecyclerView本身沒有點(diǎn)擊事件,需要在適配器中給子view添加click監(jiān)聽柔吼,然后調(diào)用我們自己的回調(diào)來實(shí)現(xiàn)毒费。有關(guān)點(diǎn)擊事件的實(shí)現(xiàn)可以參考我的另一篇文章RecyclerView --onItemClick設(shè)置匯總
getItemOffsets()
getItemOffsets
相當(dāng)于padding,相當(dāng)于設(shè)置了相對于內(nèi)容的上下左右的padding愈魏,padding出來的地方就是給onDraw方法來填充的觅玻。
getDraw
繪制在內(nèi)容的下一層相當(dāng)于內(nèi)容的背景想际。
getDrawOver
繪制在內(nèi)容的上一層,覆蓋在內(nèi)容上面溪厘,可以用于標(biāo)簽的繪制胡本。
findChildViewUnder(int x, int y)
獲取對應(yīng)X,Y的view∽耍可用于onInterceptTouchEvent
里面用于判斷當(dāng)前觸摸的view打瘪。
刪除,添加數(shù)據(jù)
注意: RecyclerView
的adapter刷新是不能用notifyDataChanged
而是根據(jù)刪除和插入數(shù)據(jù)調(diào)用不同的方法傻昙。
刪除數(shù)據(jù)之后闺骚,通知adapter
刷新數(shù)據(jù)的方法是notifyItemRemoved(int position)
.
添加數(shù)據(jù)之后,用notifyItemInserted(position)
ItemAnimator
ItemAnimator
用于RecyclerView的item的切換動畫妆档。
SimpleItemAnimator
方法解讀:
-
animateRemove(ViewHolder holder)
當(dāng)一個(gè)item要從RecyclerView中移除時(shí)僻爽,調(diào)用,而且在移除之后必須調(diào)用dispatchRemoveFinished(ViewHolder)贾惦。
getPositionByView
根據(jù)View獲取當(dāng)前View所在的position胸梆。
private int getPositionByView(View view) {
if (view == null) {
return NO_POSITION;
}
LayoutParams params = (LayoutParams) view.getLayoutParams();
if (params == null || params.isItemRemoved()) {
// when item is removed, the position value can be any value.
return NO_POSITION;
}
return params.getViewPosition();
}
requestChildFocus
requestChildFocus
是當(dāng)一個(gè)子布局要獲取焦點(diǎn)的時(shí)候調(diào)用。源碼注釋如下:
/**
* Called when a child of this parent wants focus
*
* @param child The child of this ViewParent that wants focus. This view
* will contain the focused view. It is not necessarily the view that
* actually has focus.
* @param focused The view that is a descendant of child that actually has
* focus
*/
public void requestChildFocus(View child, View focused);
從上面的英文注釋我們可以知道當(dāng)這個(gè)父布局的某個(gè)子布局要獲取焦點(diǎn)的時(shí)候這個(gè)方法就會調(diào)用须板。注意碰镜,也有可能是該子布局中的子布局要獲取焦點(diǎn)。第一個(gè)參數(shù)是父布局對應(yīng)的子布局习瑰, 第二個(gè)參數(shù)才是真正獲取焦點(diǎn)的view绪颖。從這個(gè)方法我們也可以獲取到當(dāng)前獲取焦點(diǎn)的view的位置相關(guān)的信息。
Log.i("xxx", "getPositionByView(child)" + getPositionByView(child) + focused );
LinearLayoutManager
有時(shí)候我們需要獲取當(dāng)前布局完整看到的第一個(gè)item甜奄,以及完整看到的最后一個(gè)item柠横。因?yàn)橛袝r(shí)候雖然RecyclerView我們看到的只有五個(gè),但是其實(shí)獲取第一個(gè)可見的item的position和我們預(yù)期的position不是同一個(gè)课兄,這是因?yàn)橛幸恍﹊tem雖然沒有被我們看到牍氛,但是它對于布局來說是可見的,只不過也許他只是沒有顯示內(nèi)容只顯示了邊緣,我們就認(rèn)定不可見烟阐。這個(gè)時(shí)候我們就需要通過坐標(biāo)來獲取到完全可見的item搬俊。幸運(yùn)地是,剛好LinearLayoutManager里面提供了相應(yīng)的方法蜒茄。
獲取最后一個(gè)完整可見的item的position唉擂,注意是完整可見的item的position哦。
/**
* Returns the adapter position of the last fully visible view. This position does not include
* adapter changes that were dispatched after the last layout pass.
* <p>
* Note that bounds check is only performed in the current orientation. That means, if
* LayoutManager is horizontal, it will only check the view's left and right edges.
*
* @return The adapter position of the last fully visible view or
* {@link RecyclerView#NO_POSITION} if there aren't any visible items.
* @see #findLastVisibleItemPosition()
* @see #findFirstCompletelyVisibleItemPosition()
*/
public int findLastCompletelyVisibleItemPosition() {
final View child = findOneVisibleChild(getChildCount() - 1, -1, true, false);
return child == null ? NO_POSITION : getPosition(child);
}
獲取第一個(gè)完整可見的item的position扩淀,注意是完整可見的item的position哦楔敌。
/**
* Returns the adapter position of the first fully visible view. This position does not include
* adapter changes that were dispatched after the last layout pass.
* <p>
* Note that bounds check is only performed in the current orientation. That means, if
* LayoutManager is horizontal, it will only check the view's left and right edges.
*
* @return The adapter position of the first fully visible item or
* {@link RecyclerView#NO_POSITION} if there aren't any visible items.
* @see #findFirstVisibleItemPosition()
* @see #findLastCompletelyVisibleItemPosition()
*/
public int findFirstCompletelyVisibleItemPosition() {
final View child = findOneVisibleChild(0, getChildCount(), true, false);
return child == null ? NO_POSITION : getPosition(child);
}
RecyclerView在TV上的使用
RecyclerView在TV上面使用時(shí)啤挎,要保證子布局可以獲取焦點(diǎn)否則上下鍵按鍵時(shí)布局無法移動驻谆!