LayoutManager實(shí)現(xiàn)的右滑列表

在逛Dribbble時(shí)無意間看到這樣的效果,看著挺cool的何荚,就自己來實(shí)現(xiàn)一番须教。

Dribble.gif

實(shí)現(xiàn)的效果:

效果 效果
SkidRightLayoutManager1.gif
SkidRightLayoutManager2.gif

實(shí)現(xiàn)思路是自定義LayoutManager來實(shí)現(xiàn)Item中的布局,通過RecyclerView來展示。

1.必須實(shí)現(xiàn)的方法

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

2.通過重寫onLayoutChildren方法來實(shí)現(xiàn)初始化的布局以及初始化一些需要的數(shù)據(jù)

    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        if (state.getItemCount() == 0 || state.isPreLayout()) return;
        //首先將所有的Item回收到緩存中
        removeAndRecycleAllViews(recycler);
        //第一進(jìn)來典勇,聲明Item的寬高劫哼,并標(biāo)識Item的數(shù)目不為0.
        if (!mHasChild) {
            mItemViewHeight = getVerticalSpace();
            mItemViewWidth = (int) (mItemViewHeight / mItemHeightWidthRatio);
            mHasChild = true;
        }
        mItemCount = getItemCount();
        mScrollOffset = makeScrollOffsetWithinRange(mScrollOffset);
        //對Item進(jìn)行布局
        fill(recycler);
    }

3.Item的布局以及縮放的關(guān)鍵就是在fill(recycler)函數(shù)和fillChild()函數(shù)中,同時(shí)對Item進(jìn)行回收處理

 public void fill(RecyclerView.Recycler recycler) {
        //獲取最右邊Item的位置
        int bottomItemPosition = (int) Math.floor(mScrollOffset / mItemViewWidth);
        //獲取最右邊的Item的可見寬度
        int bottomItemVisibleSize = mScrollOffset % mItemViewWidth;
        //獲取最右邊Item可見寬度相對于Item寬度的比例
        final float offsetPercent = bottomItemVisibleSize * 1.0f / mItemViewWidth;
        final int space = getHorizontalSpace();
        //用于存儲要顯示的Item的信息割笙,從最右邊的Item開始添加
        ArrayList<ItemViewInfo> layoutInfos = new ArrayList<>();
        for (int i = bottomItemPosition - 1, j = 1, remainSpace = space - mItemViewWidth;
             i >= 0; i--, j++) {
            //左右兩個(gè)Item間最大偏移量
            double maxOffset = (getHorizontalSpace() - mItemViewWidth) / 2 * Math.pow(mScale, j);
            //Item左邊的位置
            int start = (int) (remainSpace - offsetPercent * maxOffset);
            ItemViewInfo info = new ItemViewInfo(start,
                    (float) (Math.pow(mScale, j - 1) * (1 - offsetPercent * (1 - mScale))),
                    offsetPercent,
                    start * 1.0f / space
            );
            layoutInfos.add(0, info);

            remainSpace -= maxOffset;
            if (remainSpace <= 0) {
                info.setTop((int) (remainSpace + maxOffset));
                info.setPositionOffset(0);
                info.setLayoutPercent(info.getTop() / space);
                info.setScaleXY( (float) Math.pow(mScale, j - 1));
                break;
            }
        }
     
        if (bottomItemPosition < mItemCount) {
            final int start = space - bottomItemVisibleSize;
            layoutInfos.add(new ItemViewInfo(start, 1.0f,
                    bottomItemVisibleSize * 1.0f / mItemViewWidth, start * 1.0f / space).
                    setIsBottom());
        } else {
            bottomItemPosition -= 1;
        }
         //Item回收處理的邏輯
        int layoutCount = layoutInfos.size();
        final int startPos = bottomItemPosition - (layoutCount - 1);
        final int endPos = bottomItemPosition;
        final int childCount = getChildCount();
        for (int i = childCount - 1; i >= 0; i--) {
            View childView = getChildAt(i);
            int pos = convert2LayoutPosition(getPosition(childView));
            if (pos > endPos || pos < startPos) {
                removeAndRecycleView(childView, recycler);
            }
        }
        detachAndScrapAttachedViews(recycler);

        for (int i = 0; i < layoutCount; i++) {
            //將Item進(jìn)行排列
            fillChild(recycler.getViewForPosition(convert2AdapterPosition(startPos + i)), layoutInfos.get(i));
        }
    }
    private void fillChild(View view, ItemViewInfo layoutInfo) {
        addView(view);
        measureChildWithExactlySize(view);
        //計(jì)算縮放比例
        final int scaleFix = (int) (mItemViewWidth * (1 - layoutInfo.getScaleXY()) / 2);

        int top = (int) getPaddingTop();
        //排列Item
        layoutDecoratedWithMargins(view, layoutInfo.getTop() - scaleFix, top
                , layoutInfo.getTop() + mItemViewWidth - scaleFix, top + mItemViewHeight);
        //對Item進(jìn)行縮放
        ViewCompat.setScaleX(view, layoutInfo.getScaleXY());
        ViewCompat.setScaleY(view, layoutInfo.getScaleXY());
    }

4.設(shè)置列表的滑動方向

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

5.滑動處理邏輯权烧,滑動的同時(shí)也要對Item進(jìn)行位置排列

    @Override
    public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
        int pendingScrollOffset = mScrollOffset + dx;
        mScrollOffset = makeScrollOffsetWithinRange(pendingScrollOffset);
        fill(recycler);
        return mScrollOffset - pendingScrollOffset + dx;
    }

主要邏輯已將完成眯亦,一句代碼實(shí)現(xiàn)cool~~~列表

 mSkidRightLayoutManager = new SkidRightLayoutManager(1.5f, 0.85f);
        mRecyclerView.setLayoutManager(mSkidRightLayoutManager);

詳細(xì)代碼請看github源碼哦

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市般码,隨后出現(xiàn)的幾起案子妻率,更是在濱河造成了極大的恐慌,老刑警劉巖板祝,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宫静,死亡現(xiàn)場離奇詭異,居然都是意外死亡券时,警方通過查閱死者的電腦和手機(jī)孤里,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來橘洞,“玉大人捌袜,你說我怎么就攤上這事≌ㄔ妫” “怎么了虏等?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長适肠。 經(jīng)常有香客問我霍衫,道長,這世上最難降的妖魔是什么迂猴? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任慕淡,我火速辦了婚禮,結(jié)果婚禮上沸毁,老公的妹妹穿的比我還像新娘峰髓。我一直安慰自己,他們只是感情好息尺,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布携兵。 她就那樣靜靜地躺著,像睡著了一般搂誉。 火紅的嫁衣襯著肌膚如雪徐紧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天炭懊,我揣著相機(jī)與錄音并级,去河邊找鬼。 笑死侮腹,一個(gè)胖子當(dāng)著我的面吹牛嘲碧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播父阻,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼愈涩,長吁一口氣:“原來是場噩夢啊……” “哼望抽!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起履婉,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤煤篙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后毁腿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辑奈,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年狸棍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了身害。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡草戈,死狀恐怖塌鸯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情唐片,我是刑警寧澤丙猬,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站费韭,受9級特大地震影響茧球,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜星持,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一抢埋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧督暂,春花似錦揪垄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至八回,卻和暖如春酷愧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背缠诅。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工溶浴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人管引。 一個(gè)月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓士败,卻偏偏與公主長得像,于是被迫代替她去往敵國和親汉匙。 傳聞我的和親對象是個(gè)殘疾皇子拱烁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355