RecyclerView
對(duì)于android Developer來(lái)講是一個(gè)很熟悉的小伙伴了姥宝,大部分基礎(chǔ)頁(yè)面都離不開它的身影,從它的優(yōu)點(diǎn):解耦圆雁、擴(kuò)展性強(qiáng)地淀、性能出色到它的使用簡(jiǎn)單便利: adapter
專注于UI偿渡,layoutManager專注于布局臼寄、Decoration
可以繪制分割線,ItemAnimator
設(shè)置item動(dòng)畫等等溜宽,無(wú)一不能展現(xiàn)它的強(qiáng)大與優(yōu)雅吉拳,recyclerView
就像是一個(gè)美麗優(yōu)雅的女神,值得我們?nèi)?.....
開啟RecyclerView系列适揉, 主要學(xué)習(xí)
· 框架層面:低耦合留攒、擴(kuò)展性。
· 技術(shù)層面:性能友好嫉嘀、復(fù)用機(jī)制思想炼邀。
最終目標(biāo):
· 對(duì)RecyclerView知其所以然
· 玩轉(zhuǎn)各種自定義
· 完善架構(gòu)思維
· RecyclerView(1)- Decoration源碼解析
· RecyclerView(2)- 自定義Decoration打造時(shí)光軸效果
· RecyclerView(3)- LayoutMagager源碼解析,LinearLayoutManager
· RecyclerView(4)- 核心、Recycler復(fù)用機(jī)制_1
· RecyclerView(4)- 核心剪侮、Recycler復(fù)用機(jī)制_2
· RecyclerView(5)- 自定義LayoutManager(布局拭宁、復(fù)用)
· RecyclerView(6)- 自定義ItemAnimator
· RecyclerView(7)- ItemTouchHelper
· RecyclerView(8)- MultiTypeAdapter文章、MultiTypeAdapter Github地址
RecyclerView.ItemDecoration
意思名為項(xiàng)目裝飾器瓣俯,注釋是這樣寫的:
/**
* An ItemDecoration allows the application to add a special drawing and layout offset
* to specific item views from the adapter's data set. This can be useful for drawing dividers
* between items, highlights, visual grouping boundaries and more.
*
* <p>All ItemDecorations are drawn in the order they were added, before the item
* views (in {@link ItemDecoration#onDraw(Canvas, RecyclerView, RecyclerView.State) onDraw()}
* and after the items (in {@link ItemDecoration#onDrawOver(Canvas, RecyclerView,
* RecyclerView.State)}.</p>
*/
允許程序添加特殊的圖形和布局偏移量到適配器中指定的項(xiàng)目視圖杰标,可以用于項(xiàng)目視圖之間繪制分割線、高亮等等彩匕。
還指出了在項(xiàng)目之前調(diào)用onDraw()
之后調(diào)用onDrawOver
;
ItemDecoration
源碼解析
ItemDecoration
方法比較少算是比較簡(jiǎn)單腔剂,那我們就來(lái)找找 ItemDecoration
一些api在RecyclerView
中什么時(shí)候被調(diào)用吧。
主要有三個(gè)方法
getItemOffsets
設(shè)置偏移量
onDraw
在itemView 的 Canvas 中繪制裝飾
onDrawOver
RecyclerView的Canvas中繪制任何適當(dāng)?shù)难b飾
1驼仪、getItemOffsets調(diào)用
RecyclerView.class
public void measureChildWithMargins(View child, int widthUsed, int heightUsed) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
final Rect insets = mRecyclerView.getItemDecorInsetsForChild(child);
widthUsed += insets.left + insets.right;
heightUsed += insets.top + insets.bottom;
final int widthSpec = getChildMeasureSpec(getWidth(), getWidthMode(),
getPaddingLeft() + getPaddingRight() +
lp.leftMargin + lp.rightMargin + widthUsed, lp.width,
canScrollHorizontally());
final int heightSpec = getChildMeasureSpec(getHeight(), getHeightMode(),
getPaddingTop() + getPaddingBottom() +
lp.topMargin + lp.bottomMargin + heightUsed, lp.height,
canScrollVertically());
if (shouldMeasureChild(child, widthSpec, heightSpec, lp)) {
child.measure(widthSpec, heightSpec);
}
}
Rect getItemDecorInsetsForChild(View child) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (!lp.mInsetsDirty) {
return lp.mDecorInsets;
}
if (mState.isPreLayout() && (lp.isItemChanged() || lp.isViewInvalid())) {
// changed/invalid items should not be updated until they are rebound.
return lp.mDecorInsets;
}
final Rect insets = lp.mDecorInsets;
insets.set(0, 0, 0, 0);
final int decorCount = mItemDecorations.size();
for (int i = 0; i < decorCount; i++) {
mTempRect.set(0, 0, 0, 0);
mItemDecorations.get(i).getItemOffsets(mTempRect, child, this, mState);
insets.left += mTempRect.left;
insets.top += mTempRect.top;
insets.right += mTempRect.right;
insets.bottom += mTempRect.bottom;
}
lp.mInsetsDirty = false;
return insets;
}
可以看到調(diào)用getItemOffsets
的流程是這樣子的 measureChildWithMargins
-> getItemDecorInsetsForChild
-> getItemOffsets()
;
通過(guò)getItemOffsets()
得到 偏移量Rect 掸犬,再在getItemDecorInsetsForChild
中將Rect的數(shù)據(jù)添加到 insets中,在將insets中傳給 measureChildWithMargins
添加到view的外邊距中绪爸。
代碼順序是這樣的
頁(yè)面上的效果類似于下圖登渣,圖中紅框內(nèi)的白色區(qū)域就是 getItemOffsets設(shè)置之后的的效果。
2毡泻、onDraw
RecyclerView.class
@Override
public void onDraw(Canvas c) {
super.onDraw(c);
final int count = mItemDecorations.size();
for (int i = 0; i < count; i++) {
mItemDecorations.get(i).onDraw(c, this, mState);
}
}
這個(gè)就不用多講了胜茧, 上圖
有個(gè)小需要注意的地方,這邊先繪制
mItemDecorations.ondraw
之后才去繪制 itemVIew的內(nèi)容(也就是adapter中的view);
這邊如果看過(guò)view與ViewGroup源碼或者了解VIew繪制流程的同學(xué)應(yīng)該就會(huì)知道仇味,不做過(guò)多介紹呻顽。
3、onDrawOver
RecyclerView.class
public void draw(Canvas c) {
super.draw(c);
int count = this.mItemDecorations.size();
for(int i = 0; i < count; ++i) {
((RecyclerView.ItemDecoration)this.mItemDecorations.get(i)).onDrawOver(c, this, this.mState);
}
等到所有的布局都繪制完成之后丹墨,才調(diào)用 onDrawOver
廊遍。也就是說(shuō) onDrawOver是覆蓋在所有布局之上的。 下圖能看出紫色部分覆蓋了一部分itemVIew的內(nèi)容
那么其實(shí) Decoration的api調(diào)用源碼就看完了贩挣,比較簡(jiǎn)單喉前。 那么我們就可以活學(xué)活用搞點(diǎn)事情了没酣。來(lái)一個(gè)自定義吧,比如說(shuō)卵迂,時(shí)光軸效果裕便。看下圖
· RecyclerView(1)- Decoration源碼解析
· RecyclerView(2)- 自定義Decoration打造時(shí)光軸效果
· RecyclerView(3)- LayoutMagager源碼解析,LinearLayoutManager
· RecyclerView(4)- 核心见咒、Recycler復(fù)用機(jī)制_1
· RecyclerView(4)- 核心偿衰、Recycler復(fù)用機(jī)制_2
· RecyclerView(5)- 自定義LayoutManager(布局、復(fù)用)
· RecyclerView(6)- 自定義ItemAnimator
· RecyclerView(7)- ItemTouchHelper
· RecyclerView(8)- MultiTypeAdapter文章改览、MultiTypeAdapter Github地址
文章視頻地址:鏈接:http://pan.baidu.com/s/1hssvXC4 密碼:18v1
希望我的文章不會(huì)誤導(dǎo)在觀看的你下翎,如果有異議的地方歡迎討論和指正。
如果能給觀看的你帶來(lái)收獲宝当,那就是最好不過(guò)了视事。