RecyclerView(1)-Decoration源碼解析

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的外邊距中绪爸。
代碼順序是這樣的

getItemOffsets調(diào)用順序

頁(yè)面上的效果類似于下圖登渣,圖中紅框內(nèi)的白色區(qū)域就是 getItemOffsets設(shè)置之后的的效果。


getItemOffsets
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è)就不用多講了胜茧, 上圖

onDraw

有個(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)容

onDrawOver

那么其實(shí) Decoration的api調(diào)用源碼就看完了贩挣,比較簡(jiǎn)單喉前。 那么我們就可以活學(xué)活用搞點(diǎn)事情了没酣。來(lái)一個(gè)自定義吧,比如說(shuō)卵迂,時(shí)光軸效果裕便。看下圖

時(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ò)了视事。

人生得意須盡歡, 桃花塢里桃花庵
點(diǎn)個(gè)關(guān)注唄,對(duì)庆揩,不信你點(diǎn)試試郑口?
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市盾鳞,隨后出現(xiàn)的幾起案子犬性,更是在濱河造成了極大的恐慌,老刑警劉巖腾仅,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件乒裆,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡推励,警方通過(guò)查閱死者的電腦和手機(jī)鹤耍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)验辞,“玉大人稿黄,你說(shuō)我怎么就攤上這事〉欤” “怎么了杆怕?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)壳贪。 經(jīng)常有香客問(wèn)我陵珍,道長(zhǎng),這世上最難降的妖魔是什么违施? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任互纯,我火速辦了婚禮,結(jié)果婚禮上磕蒲,老公的妹妹穿的比我還像新娘留潦。我一直安慰自己只盹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布兔院。 她就那樣靜靜地躺著殖卑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪秆乳。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天钻哩,我揣著相機(jī)與錄音屹堰,去河邊找鬼。 笑死街氢,一個(gè)胖子當(dāng)著我的面吹牛扯键,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播珊肃,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼荣刑,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了伦乔?” 一聲冷哼從身側(cè)響起厉亏,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤邑跪,失蹤者是張志新(化名)和其女友劉穎饭耳,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體凰兑,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡招刹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年恬试,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疯暑。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡训柴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出妇拯,到底是詐尸還是另有隱情幻馁,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布越锈,位于F島的核電站宣赔,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏瞪浸。R本人自食惡果不足惜儒将,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望对蒲。 院中可真熱鬧钩蚊,春花似錦贡翘、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至蝠咆,卻和暖如春踊东,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背刚操。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工闸翅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人菊霜。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓坚冀,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親鉴逞。 傳聞我的和親對(duì)象是個(gè)殘疾皇子记某,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • RecyclerView 源碼分析 本文原創(chuàng),轉(zhuǎn)載請(qǐng)注明出處构捡。歡迎關(guān)注我的 簡(jiǎn)書 液南,關(guān)注我的專題 Android ...
    MeloDev閱讀 10,082評(píng)論 6 49
  • 這篇文章分三個(gè)部分,簡(jiǎn)單跟大家講一下 RecyclerView 的常用方法與奇葩用法勾徽;工作原理與ListView比...
    LucasAdam閱讀 4,377評(píng)論 0 27
  • 特別聲明: 本文轉(zhuǎn)發(fā)自:【江清清的博客】http://blog.csdn.net/developer_jiangq...
    _猜火車_閱讀 37,392評(píng)論 11 70
  • 一.提交已寫好的項(xiàng)目文件到云端贺拣。 以前幾天建的firstapp為例,將此文件提交到已建的庫(kù)gitTest中: 1....
    qzuser_e750閱讀 220評(píng)論 0 0
  • 你說(shuō)愛捂蕴, 我就看到美妙的可樂譬涡。 你說(shuō)云, 我就看到我們的夢(mèng)啥辨。 你說(shuō)風(fēng)涡匀, 我就看到自由的世界。 你所說(shuō)的溉知, 一路的風(fēng)...
    伍月的晴空閱讀 360評(píng)論 4 6