ScatteredLayoutManager顾瞻,錯(cuò)落排列的RecyclerView布局

效果如下圖所示:
Screenshot_2018-08-13-11-57-45.png

LayoutManager已經(jīng)有很多博客分享過自定義的方法和注意事項(xiàng),目前我也在學(xué)習(xí)顺少,不班門弄斧講原理朋其。這個(gè)效果是在一個(gè)app上看到的,直接上實(shí)現(xiàn)代碼脆炎,有需要的可以參考一下梅猿。

public class ScatteredLayoutManager extends RecyclerView.LayoutManager {

    private int verticalScrollOffset;
    private int offsetH = 0;
    private int leftMargin, rightMargin;

    @Override
    public RecyclerView.LayoutParams generateDefaultLayoutParams() {
        return new RecyclerView.LayoutParams(RecyclerView.LayoutParams.WRAP_CONTENT, RecyclerView.LayoutParams.WRAP_CONTENT);
    }

    @Override
    public boolean isAutoMeasureEnabled() {
        return true;
    }

    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        super.onLayoutChildren(recycler, state);
        if (getItemCount() == 0) {
            detachAndScrapAttachedViews(recycler);
            return;
        }
        if (getChildCount() == 0 && state.isPreLayout()) {
            return;
        }
        RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
                recycler.getViewForPosition(0).getLayoutParams();
        leftMargin = params.leftMargin;
        rightMargin = params.rightMargin;
        //先把所有item從RecyclerView中detach
        detachAndScrapAttachedViews(recycler);
        layoutItem(recycler);
    }

    private void layoutItem(RecyclerView.Recycler recycler) {
        offsetH = getPaddingTop();

        int width = (Resources.getSystem().getDisplayMetrics().widthPixels
                - getRightDecorationWidth(recycler.getViewForPosition(0))
                - getLeftDecorationWidth(recycler.getViewForPosition(0))
                - leftMargin - rightMargin) / 3;
        int round = 0;
        for (int i = 0; i < getItemCount(); i++) {
            View view = recycler.getViewForPosition(i);
            addView(view); // 因?yàn)閐etach過所以重新添加
            measureChildWithMargins(view, 0, 0);
            int height = getDecoratedMeasuredHeight(view);

            Rect mTmpRect = new Rect();
            calculateItemDecorationsForChild(view, mTmpRect);
            switch (i - round) {
                case 0:
                    layoutDecoratedWithMargins(view, 0, offsetH, 2 * width, offsetH + height);
                    break;
                case 1:
                    layoutDecoratedWithMargins(view, 2 * width, offsetH,
                            3 * width, offsetH + height / 2);
                    break;
                case 2:
                    layoutDecoratedWithMargins(view, 2 * width, offsetH + height / 2,
                            3 * width, offsetH + height);
                    offsetH = offsetH + height;
                    break;
                case 3:
                    layoutDecoratedWithMargins(view, 0, offsetH,
                            width, offsetH + height / 2);
                    break;
                case 4:
                    layoutDecoratedWithMargins(view, 0, offsetH + height / 2,
                            width, offsetH + height);
                    break;
                case 5:
                    layoutDecoratedWithMargins(view, width, offsetH,
                            3 * width, offsetH + height);
                    offsetH = offsetH + height;
                    break;
                default:
                    layoutDecoratedWithMargins(view, 0, offsetH, 3 * width,
                            offsetH + height);
                    offsetH = offsetH + height;
                    break;
            }
            if (i + 1 - round == 6)
                round += 6;
        }
    }

    @Override
    public boolean canScrollVertically() {
        return true;
    }

    @Override
    public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
        //列表向下滾動(dòng)dy為正,列表向上滾動(dòng)dy為負(fù)秒裕,這點(diǎn)與Android坐標(biāo)系保持一致袱蚓。
        //實(shí)際要滑動(dòng)的距離
        int travel = dy;
        //如果滑動(dòng)到最頂部
        if (verticalScrollOffset + dy < 0) {
            travel = -verticalScrollOffset;
        } else if (verticalScrollOffset + dy > offsetH - getVerticalSpace()) {//如果滑動(dòng)到最底部
            travel = offsetH - getVerticalSpace() - verticalScrollOffset;
        }
        //將豎直方向的偏移量+travel
        verticalScrollOffset += travel;
        // 調(diào)用該方法通知view在y方向上移動(dòng)指定距離
        offsetChildrenVertical(-travel);

        return travel;
    }

    private int getVerticalSpace() {
        //計(jì)算RecyclerView的可用高度,除去上下Padding值
        return getHeight() - getPaddingBottom() - getPaddingTop();
    }
}

說明:目前只是將item的布局實(shí)現(xiàn)几蜻,并且讓列表滾動(dòng)起來喇潘,還沒時(shí)間去寫復(fù)用的代碼和一些優(yōu)化,有時(shí)間會(huì)更新梭稚。

https://github.com/HarveyLee1228/ScatteredLayoutManager

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末颖低,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子弧烤,更是在濱河造成了極大的恐慌忱屑,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件暇昂,死亡現(xiàn)場離奇詭異莺戒,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)急波,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門从铲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人澄暮,你說我怎么就攤上這事名段。” “怎么了泣懊?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵吉嫩,是天一觀的道長。 經(jīng)常有香客問我嗅定,道長自娩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮忙迁,結(jié)果婚禮上脐彩,老公的妹妹穿的比我還像新娘。我一直安慰自己姊扔,他們只是感情好惠奸,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著恰梢,像睡著了一般佛南。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嵌言,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天嗅回,我揣著相機(jī)與錄音,去河邊找鬼摧茴。 笑死绵载,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的苛白。 我是一名探鬼主播娃豹,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼购裙!你這毒婦竟也來了懂版?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤躏率,失蹤者是張志新(化名)和其女友劉穎定续,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體禾锤,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年摹察,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了恩掷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡供嚎,死狀恐怖黄娘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情克滴,我是刑警寧澤逼争,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站劝赔,受9級特大地震影響誓焦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜着帽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一杂伟、第九天 我趴在偏房一處隱蔽的房頂上張望移层。 院中可真熱鬧,春花似錦赫粥、人聲如沸观话。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽频蛔。三九已至,卻和暖如春秦叛,著一層夾襖步出監(jiān)牢的瞬間晦溪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工书闸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留尼变,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓浆劲,卻偏偏與公主長得像嫌术,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子牌借,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評論 2 345

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