Android中RecyclerView嵌套RecyclerView或嵌套ListView

效果图:

RecyclerView嵌套RecyclerView

RecyclerView嵌套ListView

 

原理

 

RecyclerView嵌套RecyclerView的条目,项目中可能会经常有这样的需求,但是我们将子条目设置为RecyclerView之后,却显示不出来。自己试了很久,终于找到了原因:必须先设置子RecylcerView的高度。你要花精力确定出子RecyclerView里面条目的高度,然后从而确定子RecyclerView的高度,设置给子RecylcerView,这样做RecyclerView就可以正确显示出子ReclyclerView。

代码

首页布局就是一个竖直排列的RecyclerView

 
  1. xmlns:android="http://schemas.android.com/apk/res/android"

  2. android:id="@+id/recylcerview"

  3. android:layout_width="match_parent"

  4. android:layout_height="match_parent"/>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

接下来在MainActivity对该布局进行初始化,然后制造一些假数据

 
  1. protected void onCreate(Bundle savedInstanceState) {

  2. super.onCreate(savedInstanceState);

  3. setContentView(R.layout.activity_main);

  4. basicParamInit();

  5. initData();

  6. initRecyclerView();

  7. }

  8.  
  9.  
  10.  
  11. private void basicParamInit() {

  12. DisplayMetrics metric = new DisplayMetrics();

  13. getWindowManager().getDefaultDisplay().getMetrics(metric);

  14.  
  15. screenWidth = metric.widthPixels;

  16.  
  17. }

  18. private void initData() {

  19. data = new DataInfor();

  20. ArrayList resourceList =new ArrayList<>();

  21.  
  22. resourceList.add(R.drawable.aaa);

  23. resourceList.add(R.mipmap.ic_launcher);

  24. resourceList.add(R.drawable.aaa);

  25. resourceList.add(R.mipmap.ic_launcher);

  26. resourceList.add(R.drawable.aaa);

  27. resourceList.add(R.mipmap.ic_launcher);

  28. resourceList.add(R.drawable.aaa);

  29. resourceList.add(R.mipmap.ic_launcher);

  30.  
  31. data.gridData = data.horizontalData = data.verticalData = resourceList;

  32.  
  33. }

  34.  
  35. private void initRecyclerView() {

  36. recylcerview = (RecyclerView) findViewById(R.id.recylcerview);

  37.  
  38. recylcerview.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL,false));

  39.  
  40. recylcerview.setBackgroundResource(R.color.c_e0e0e2);

  41.  
  42. recylcerview.setAdapter(new RecyclerViewAdapter());

  43. }

  • 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:

 
  1. private class RecyclerViewAdapter extends RecyclerView.Adapter{

  2. private final int HORIZONTAL_VIEW = 1000;

  3. private final int VERTICAL_VIEW = 1001;

  4. private final int GRID_VIEW = 1002;

  5.  
  6. @Override

  7. public BaseHolder onCreateViewHolder(ViewGroup parent, int viewType) {

  8. switch (viewType){

  9. case HORIZONTAL_VIEW:

  10. return new HorizontalViewHolder(R.layout.item_recyclerview,parent,viewType);

  11. case GRID_VIEW:

  12. return new GridViewHolder(R.layout.item_recyclerview,parent,viewType);

  13. case VERTICAL_VIEW:

  14. return new ItemViewHolder(R.layout.item_x2_imageview,parent,viewType);

  15. }

  16. return null;

  17. }

  18.  
  19. @Override

  20. public void onBindViewHolder(BaseHolder holder, int position) {

  21. if(holder instanceof HorizontalViewHolder){

  22. holder.refreshData(data.horizontalData,position);

  23. }else if(holder instanceof GridViewHolder){

  24. holder.refreshData(data.gridData,position);

  25. }else if(holder instanceof ItemViewHolder){

  26. holder.refreshData(data.verticalData.get(position - 2),position - 2);

  27. }

  28.  
  29. }

  30.  
  31. @Override

  32. public int getItemCount() {

  33. return 2 + data.verticalData.size();

  34. }

  35.  
  36. @Override

  37. public int getItemViewType(int position) {

  38. if(position == 0) return HORIZONTAL_VIEW;

  39. if(position == 1) return GRID_VIEW;

  40. return VERTICAL_VIEW;

  41. }

  42. }

  • 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

 
  1. private class HorizontalViewHolder extends BaseHolder>{

  2. private RecyclerView hor_recyclerview;

  3.  
  4. private List data;

  5.  
  6. public HorizontalViewHolder(int viewId, ViewGroup parent, int viewType) {

  7. super(viewId, parent, viewType);

  8. hor_recyclerview = (RecyclerView) itemView.findViewById(R.id.item_recyclerview);

  9. }

  10.  
  11. @Override

  12. public void refreshData(List data, int position) {

  13. this.data = data;

  14. ViewGroup.LayoutParams layoutParams = hor_recyclerview.getLayoutParams();

  15. //高度等于=条目的高度+ 10dp的间距 + 10dp(为了让条目居中)

  16. layoutParams.height = screenWidth/3 + dip2px(20);

  17. hor_recyclerview.setLayoutParams(layoutParams);

  18. hor_recyclerview.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL,false));

  19. hor_recyclerview.setBackgroundResource(R.color.colorAccent);

  20. hor_recyclerview.setAdapter(new HorizontalAdapter());

  21. }

  22.  
  23. private class HorizontalAdapter extends RecyclerView.Adapter{

  24.  
  25. @Override

  26. public BaseHolder onCreateViewHolder(ViewGroup parent, int viewType) {

  27. return new ItemViewHolder(R.layout.item_x2_imageview,parent,viewType);

  28. }

  29.  
  30. @Override

  31. public void onBindViewHolder(BaseHolder holder, int position) {

  32. holder.refreshData(data.get(position),position);

  33. }

  34.  
  35. @Override

  36. public int getItemCount() {

  37. return data.size();

  38. }

  39. }

  40. }

  • 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的高度

 
  1. private class GridViewHolder extends BaseHolder>{

  2.  
  3. private RecyclerView item_recyclerview;

  4.  
  5. private final int ONE_LINE_SHOW_NUMBER = 3;

  6.  
  7. private List data;

  8.  
  9. public GridViewHolder(int viewId, ViewGroup parent, int viewType) {

  10. super(viewId, parent, viewType);

  11. item_recyclerview = (RecyclerView) itemView.findViewById(R.id.item_recyclerview);

  12.  
  13. }

  14.  
  15. @Override

  16. public void refreshData(List data, int position) {

  17. super.refreshData(data, position);

  18. this.data = data;

  19. //每行显示3个,水平显示

  20. item_recyclerview.setLayoutManager(new GridLayoutManager(MainActivity.this,ONE_LINE_SHOW_NUMBER,LinearLayoutManager.HORIZONTAL,false));

  21.  
  22. ViewGroup.LayoutParams layoutParams = item_recyclerview.getLayoutParams();

  23. //计算行数

  24. int lineNumber = data.size()%ONE_LINE_SHOW_NUMBER==0? data.size()/ONE_LINE_SHOW_NUMBER:data.size()/ONE_LINE_SHOW_NUMBER +1;

  25. //计算高度=行数*每行的高度 +(行数-1)*10dp的margin + 10dp(为了居中)

  26. //因为每行显示3个条目,为了保持正方形,那么高度应该是也是宽度/3

  27. //高度的计算需要自己好好理解,否则会产生嵌套recyclerView可以滑动的现象

  28. layoutParams.height = lineNumber *(screenWidth/3) + (lineNumber-1)*dip2px(10) + dip2px(10);

  29.  
  30. item_recyclerview.setLayoutParams(layoutParams);

  31.  
  32. item_recyclerview.setBackgroundResource(R.color.colorPrimary);

  33.  
  34. item_recyclerview.setAdapter(new GridAdapter());

  35. }

  36.  
  37.  
  38. private class GridAdapter extends RecyclerView.Adapter{

  39.  
  40. @Override

  41. public BaseHolder onCreateViewHolder(ViewGroup parent, int viewType) {

  42. return new ItemViewHolder(R.layout.item_x2_imageview,parent,viewType);

  43. }

  44.  
  45. @Override

  46. public void onBindViewHolder(BaseHolder holder, int position) {

  47. holder.refreshData(data.get(position),position);

  48. }

  49.  
  50. @Override

  51. public int getItemCount() {

  52. return data.size();

  53. }

  54. }

  55.  
  56.  
  57. }

  • 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

其他代码我就不贴了,想要看源码的可以直接下载: 
https://github.com/z593492734/nesting-recylcerview

总体来说,RecyclerView嵌套RecyclerView是很简单的,而且也相当好用,希望这个demo可以给大家一些灵感。

有任何问题都可以联系我:[email protected]

下面是我修改后的例子:

效果图:

源码下载:

http://download.csdn.net/detail/zhaihaohao1/9571152

转载地址:

http://blog.csdn.net/z593492734/article/details/51492472

--------------------- 本文来自 zhaihaohao1 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/zhaihaohao1/article/details/51863081?utm_source=copy

你可能感兴趣的:(android)