1. 程式人生 > >左右兩側兩個RecyclerView互相聯動,類似美團外賣點餐

左右兩側兩個RecyclerView互相聯動,類似美團外賣點餐

概述

最近做專案需要用到兩個RecyclerView互相聯動的功能,類似美團外賣的點餐列表,不同的是專案用到的右側是點選分類,所以我用了左側RecyclerView和右側RecyclerView包含兩個TextView和GridView,然後找了很多資料,把遇到的問題記錄下來和大家一起分享,有類似需要的朋友可以看一下。先上圖:

                   

需求:

1.左側聯動右側,點選左側任意一項、背景變色、右側對應位置滾動到頂部。

2.右側聯動左側,右側滾動,左側需要同步右側在頂部的位置。

3.就像圖中所示,點選圖1的9,會向下移動到中間位置,點選圖2的12,會向上移動到中間位置。

左側聯動右側

左側聯動右側,在右側側RecyclerView的介面卡中自定義一個得到position的方法,這個position從左側的點選事件中傳過來

 public void getSelectedPosition(int selectedPosition) {
        //呼叫移動位置的方法,直接移動到頂部第一個位置
        ((LinearLayoutManager)recyclerView.getLayoutManager()).scrollToPositionWithOffset(selectedPosition,0);
        //重新整理
        notifyDataSetChanged();
    }

右側聯動左側,並將左側移動到中間位置

說一下大體思路吧,獲得當前螢幕可見的第一項和最後一項,算出他們的中間值,通過getTop方法得到傳入的position距離中間值的高度,然後呼叫scrollBy方法,注意在中間值的上方和下方要滑動的方向是不一樣的。

需要注意這裡有一個注意事項,就是getChildAt方法無法獲取超出螢幕外的position的項,如果index大於螢幕中可見的Item數會返回null,左側並沒有滑動的監聽,比如左側滑動到最底部,右側還在第一項,右側往上滑動會直接程式崩潰,那麼如果index大於螢幕中Item的數量,我們直接使用ScrollToPosition。

直接上程式碼吧:

public void moveToMiddle(int position) {
        //先從RecyclerView的LayoutManager中獲取當前第一項和最後一項的Position
        int firstItem = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition();
        int lastItem = ((LinearLayoutManager) recyclerView.getLayoutManager()).findLastVisibleItemPosition();
        //中間位置
        int middle = (firstItem + lastItem)/2;
        // 取絕對值,index下標是當前的位置和中間位置的差,下標為index的view的top就是需要滑動的距離
        int index = (position - middle) >= 0 ? position - middle : -(position - middle);
        //左側列表一共有12個Item,如果>這個值會返回null,程式崩潰,如果>12直接滑到指定位置,或者getChildCount,都一樣啦
        if (index >= recyclerView.getChildCount()) {
            recyclerView.scrollToPosition(position);
        } else {
            //如果當前位置在中間位置上面,往下移動,這裡為了防止越界
            if(position < middle) {
               recyclerView.scrollBy(0, -recyclerView.getChildAt(index).getTop());
               // 在中間位置的下面,往上移動
            } else {
                recyclerView.scrollBy(0, recyclerView.getChildAt(index).getTop());
            }
        }
    }

總結

以上內容就是左右兩側聯動的重點,其他基礎的我也簡單說一下:

首先介面卡中要自己定義一個方法如getSelectedPosition來獲得activity傳回來的position,利用這個position,左側在activity中獲取自身的點選position和右側滾動傳來的position,然後可以在onBindViewHolder中設定背景色的變化,以及傳入moveToMiddle中,右側也一樣,從activity中獲取左側的傳來的position,進行滑動反饋。

RecyclerView沒提供點選事件,需要自定義listener介面,ViewHolder中item的點選方法得到選中的position,呼叫自定義listener的onItemClick方法,傳入position,listener的onItemClick方法在activity中被重寫,呼叫介面卡的getSelectedPosition向介面卡中返回position。

右側RecyclerView的GridView的使用和listView類似,注意一個問題就是GridView巢狀在其他佈局內,只顯示一行,需要重寫GridView的onMeasure方法,自定義一個GridView。

至於資料問題,我上傳的Demo是自己模擬的相同的資料,實際開發中一般需要從JSON中解析得來,那就是Json解析的問題了,附上Demo,大家一起學習。

原始碼地址:https://github.com/pengboboer/TwoRecyclerVIew

後續

如果想學習RecyclerView的使用,推薦大家看鴻洋大神的部落格,寫的很詳細了。