1. 程式人生 > >Android中RecyclerView巢狀RecyclerView或巢狀ListView

Android中RecyclerView巢狀RecyclerView或巢狀ListView

效果圖:

RecyclerView巢狀RecyclerView


RecyclerView巢狀ListView


原理

RecyclerView巢狀RecyclerView的條目,專案中可能會經常有這樣的需求,但是我們將子條目設定為RecyclerView之後,卻顯示不出來。自己試了很久,終於找到了原因:必須先設定子RecylcerView的高度。你要花精力確定出子RecyclerView裡面條目的高度,然後從而確定子RecyclerView的高度,設定給子RecylcerView,這樣做RecyclerView就可以正確顯示出子ReclyclerView。

程式碼

首頁佈局就是一個豎直排列的RecyclerView

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/recylcerview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

接下來在MainActivity對該佈局進行初始化,然後製造一些假資料

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        basicParamInit();
        initData();
        initRecyclerView();
    }



    private  void basicParamInit() {
        DisplayMetrics metric = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metric); screenWidth = metric.widthPixels; } private void initData() { data = new DataInfor(); ArrayList<Integer> resourceList =new ArrayList<>(); resourceList.add(R.drawable.aaa); resourceList.add(R.mipmap.ic_launcher); resourceList.add(R.drawable.aaa); resourceList.add(R.mipmap.ic_launcher); resourceList.add(R.drawable.aaa); resourceList.add(R.mipmap.ic_launcher); resourceList.add(R.drawable.aaa); resourceList.add(R.mipmap.ic_launcher); data.gridData = data.horizontalData = data.verticalData = resourceList; } private void initRecyclerView() { recylcerview = (RecyclerView) findViewById(R.id.recylcerview); recylcerview.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL,false)); recylcerview.setBackgroundResource(R.color.c_e0e0e2); recylcerview.setAdapter(new RecyclerViewAdapter()); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

接下來看看RecyclerView的Adapter:

private class RecyclerViewAdapter extends RecyclerView.Adapter<BaseHolder>{
        private final int HORIZONTAL_VIEW = 1000;
        private final int VERTICAL_VIEW = 1001;
        private final int GRID_VIEW = 1002;

        @Override
        public BaseHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            switch (viewType){
                case HORIZONTAL_VIEW:
                    return new HorizontalViewHolder(R.layout.item_recyclerview,parent,viewType);
                case GRID_VIEW:
                    return new GridViewHolder(R.layout.item_recyclerview,parent,viewType);
                case VERTICAL_VIEW:
                    return new ItemViewHolder(R.layout.item_x2_imageview,parent,viewType);
            }
            return null;
        }

        @Override
        public void onBindViewHolder(BaseHolder holder, int position) {
            if(holder instanceof HorizontalViewHolder){
                holder.refreshData(data.horizontalData,position);
            }else if(holder instanceof GridViewHolder){
                holder.refreshData(data.gridData,position);
            }else if(holder instanceof ItemViewHolder){
                holder.refreshData(data.verticalData.get(position - 2),position - 2);
            }

        }

        @Override
        public int getItemCount() {
            return 2 + data.verticalData.size();
        }

        @Override
        public int getItemViewType(int position) {
            if(position == 0) return HORIZONTAL_VIEW;
            if(position == 1) return GRID_VIEW;
            return VERTICAL_VIEW;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

可以看出,我們一共有三種條目型別,第一種是水平滑動的子RecyclerView,第二種是GridView形的子RecyclerView,第三種就是正常的子條目,根據viewType來返回不同的ViewHolder,到這裡應該都沒什麼問題。

接下來就是各個型別的ViewHolder了,在Holder當中,我們要計算條目的高度然後設定給子RecyclerView

    private class HorizontalViewHolder extends BaseHolder<List<Integer>>{
        private RecyclerView hor_recyclerview;

        private List<Integer> data;

        public HorizontalViewHolder(int viewId, ViewGroup parent, int viewType) {
            super(viewId, parent, viewType);
            hor_recyclerview = (RecyclerView) itemView.findViewById(R.id.item_recyclerview);
        }

        @Override
        public void refreshData(List<Integer> data, int position) {
            this.data = data;
            ViewGroup.LayoutParams layoutParams = hor_recyclerview.getLayoutParams();
            //高度等於=條目的高度+ 10dp的間距 + 10dp(為了讓條目居中)
            layoutParams.height = screenWidth/3 + dip2px(20);
            hor_recyclerview.setLayoutParams(layoutParams);
            hor_recyclerview.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL,false));
            hor_recyclerview.setBackgroundResource(R.color.colorAccent);
            hor_recyclerview.setAdapter(new HorizontalAdapter());
        }

        private class HorizontalAdapter extends RecyclerView.Adapter<BaseHolder>{

            @Override
            public BaseHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                return new ItemViewHolder(R.layout.item_x2_imageview,parent,viewType);
            }

            @Override
            public void onBindViewHolder(BaseHolder holder, int position) {
                holder.refreshData(data.get(position),position);
            }

            @Override
            public int getItemCount() {
                return data.size();
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

水平的子RecyclerView的高度還是比較容易計算的,畢竟只有一行,高度相對來說是固定的。但是像GridView的高度是動態的,根據條目數量的不同,可能會有多行,所以我們需要先計算行數,然後每行的高度*行數才是子RecyclerView的高度

private class GridViewHolder extends BaseHolder<List<Integer>>{

        private RecyclerView item_recyclerview;

        private final int ONE_LINE_SHOW_NUMBER = 3;

        private List<Integer> data;

        public GridViewHolder(int viewId, ViewGroup parent, int viewType) {
            super(viewId, parent, viewType);
            item_recyclerview = (RecyclerView) itemView.findViewById(R.id.item_recyclerview);

        }

        @Override
        public void refreshData(List<Integer> data, int position) {
            super.refreshData(data, position);
            this.data = data;
            //每行顯示3個,水平顯示
            item_recyclerview.setLayoutManager(new GridLayoutManager(MainActivity.this,ONE_LINE_SHOW_NUMBER,LinearLayoutManager.HORIZONTAL,false));

            ViewGroup.LayoutParams layoutParams = item_recyclerview.getLayoutParams();
            //計算行數
            int lineNumber = data.size()%ONE_LINE_SHOW_NUMBER==0? data.size()/ONE_LINE_SHOW_NUMBER:data.size()/ONE_LINE_SHOW_NUMBER +1;
            //計算高度=行數*每行的高度 +(行數-1)*10dp的margin + 10dp(為了居中)
            //因為每行顯示3個條目,為了保持正方形,那麼高度應該是也是寬度/3
            //高度的計算需要自己好好理解,否則會產生巢狀recyclerView可以滑動的現象
            layoutParams.height = lineNumber *(screenWidth/3) + (lineNumber-1)*dip2px(10) + dip2px(10);

            item_recyclerview.setLayoutParams(layoutParams);

            item_recyclerview.setBackgroundResource(R.color.colorPrimary);

            item_recyclerview.setAdapter(new GridAdapter());
        }


        private class GridAdapter extends RecyclerView.Adapter<BaseHolder>{

            @Override
            public BaseHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                return new ItemViewHolder(R.layout.item_x2_imageview,parent,viewType);
            }

            @Override
            public void onBindViewHolder(BaseHolder holder, int position) {
                holder.refreshData(data.get(position),position);
            }

            @Override
            public int getItemCount() {
                return data.size();
            }
        }


    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

總體來說,RecyclerView巢狀RecyclerView是很簡單的,而且也相當好用,希望這個demo可以給大家一些靈感。

有任何問題都可以聯絡我:[email protected]

下面是我修改後的例子:

效果圖:


原始碼下載:

轉載地址: