微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Android中RecyclerView嵌套RecyclerView或嵌套ListView

 

效果图:

RecyclerView嵌套RecyclerView

RecyclerView嵌套ListView

 

原理

 

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

代码

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

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

 

接下来看看RecyclerView的Adapter:

  1.   private class RecyclerViewAdapter extends RecyclerView.Adapter<BaseHolder>{
  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.   }

 

可以看出,我们一共有三种条目类型,第一种是水平滑动的子RecyclerView,第二种是GridView形的子RecyclerView,第三种就是正常的子条目,根据viewType来返回不同的ViewHolder,到这里应该都没什么问题。

接下来就是各个类型的ViewHolder了,在Holder当中,我们要计算条目的高度然后设置给子RecyclerView

  1.   private class HorizontalViewHolder extends BaseHolder<List<Integer>>{
  2.   private RecyclerView hor_recyclerview;
  3.    
  4.   private List<Integer> 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<Integer> 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<BaseHolder>{
  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.   }

水平的子RecyclerView的高度还是比较容易计算的,毕竟只有一行,高度相对来说是固定的。但是像GridView的高度是动态的,根据条目数量的不同,可能会有多行,所以我们需要先计算行数,然后每行的高度*行数才是子RecyclerView的高度

  1.   private class GridViewHolder extends BaseHolder<List<Integer>>{
  2.    
  3.   private RecyclerView item_recyclerview;
  4.    
  5.   private final int ONE_LINE_SHOW_NUMBER = 3;
  6.    
  7.   private List<Integer> 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<Integer> 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<BaseHolder>{
  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.   }

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

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

有任何问题都可以联系我:mengyuanzz@126.com

下面是我修改后的例子:

效果图:

源码下载:

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

转载地址:

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐