为RecyclerView的不同item项实现不同的布局(添加分类Header)
最近在做一个应用的时候,需要为GridLayoutManager添加头部header,然后自然而然就想到了用不同的itemType去加载不同的布局。
1.实现多item布局,用不同的itemType去加载不同的布局。
主要思路就是先定义好标识itemType的常量,然后重写getItemViewType()方法,根据不同的位置(position)返回不同的Type,接着在onCreateViewHolder()中根据参数viewType去判断该item项应该 inflate 哪个布局文件,并返回相应的ViewHolder实例(这里ViewHolder是根据不同的item布局预先自定义好的不同的ViewHolder)
比如我的代码:
 public class MyRecyclerCardviewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{  
     public static enum ITEM_TYPE {
         ITEM_TYPE_Theme,
         ITEM_TYPE_Video
     }
     //数据集
     public List<Integer> mdatas;
     private TextView themeTitle;  
     public MyRecyclerCardviewAdapter(List<Integer> datas){
         super();
         this.mdatas = datas;
     }  
     @Override
     public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {  
         if (viewType == ITEM_TYPE.ITEM_TYPE_Theme.ordinal()){  
             View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.videothemelist,parent,false);  
             return new ThemeVideoHolder(view);  
         }else if(viewType == ITEM_TYPE.ITEM_TYPE_Video.ordinal()){  
             View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.videocardview,parent,false);
             return new VideoViewHolder(view);  
         }
           return null;
     }  
     @Override
     public void onBindViewHolder(final ViewHolder holder, final int position) {  
         if (holder instanceof ThemeVideoHolder){  
            themeTitle.setText("励志");  
         }else if (holder instanceof VideoViewHolder){
             ((VideoViewHolder)holder).videologo.setImageResource(R.drawable.lianzai_02);
             ((VideoViewHolder)holder).videovname.setText("励志,俄小伙练习街头健身一年的体型变化,Dear Hard Work!");
             ((VideoViewHolder)holder).videoviewed.setText("2780次");
             ((VideoViewHolder)holder).videocomment.setText("209条");  
           }  
     }  
     public int getItemViewType(int position){  
         return position % 5 == 0 ? ITEM_TYPE.ITEM_TYPE_Theme.ordinal() : ITEM_TYPE.ITEM_TYPE_Video.ordinal();
     }  
     @Override
     public int getItemCount() {
         return mdatas.size();
     }  
     public class ThemeVideoHolder extends RecyclerView.ViewHolder{  
         public ThemeVideoHolder(View itemView) {
             super(itemView);
             themeTitle = (TextView) itemView.findViewById(R.id.hometab1_theme_title);
         }
     }  
     public class VideoViewHolder extends RecyclerView.ViewHolder {
         public ImageView videologo;
         public TextView videovname;
         public TextView videoviewed;
         public TextView videocomment;  
         public VideoViewHolder(View itemView) {
             super(itemView);
             videologo = (ImageView) itemView.findViewById(R.id.videologo);
             videoviewed = (TextView) itemView.findViewById(R.id.videoviewed);
             videocomment = (TextView) itemView.findViewById(R.id.videocomment);
             videovname = (TextView) itemView.findViewById(R.id.videoname);
         }
     }
 }  
这时,使用的是 LayoutManager 中发 LinearLayoutManager,效果图如下:

但是,当我们把 LayoutManager 改成GridLayoutManager的时候你就出现了不是我们期待的效果,如下图:

What the hell is going on? 什么鬼?怎么添加的header随着其他item项以cell的形式出现在网格上。仔细想一想,发现了下面代码
GridLayoutManager layoutManager = new GridLayoutManager(this,2, GridLayoutManager.VERTICAL,false);
哦!原来我们在创建GridLayoutManager的时候需要设定每行显示多少个item项,我们这里设置的是2,而我们添加的header是以item项的形式添加进来的,所以也会以cell的形式出现。那么,有没有办法让header这个item占据两个cell,单独霸占一行呢?答案是肯定的,我们可以通过setSpanSizeLookup抽象类中的getSpanSize()方法的返回值来设定每个item项占据多少个单元格 。
 gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
             @Override
             public int getSpanSize(int position) {
                 return getItemViewType(position) == ITEM_TYPE.ITEM_TYPE_Theme.ordinal()
                         ? gridManager.getSpanCount() : 1;
             }
         });  
那么,这段代码在自定义Adapter中应该添加在何处呢?放在onAttachedToRecyclerView()中再合适不过了。
 public void onAttachedToRecyclerView(RecyclerView recyclerView) {
         super.onAttachedToRecyclerView(recyclerView);
         RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
         if(manager instanceof GridLayoutManager) {
             final GridLayoutManager gridManager = ((GridLayoutManager) manager);
             gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                 @Override
                 public int getSpanSize(int position) {
                     return getItemViewType(position) == ITEM_TYPE.ITEM_TYPE_Theme.ordinal()
                             ? gridManager.getSpanCount() : 1;
                 }
             });
         }
     }  
这时就可以实现我想要的效果了,运行效果图如下:

代码我已经抽离出来放到我的Github了:RecycleViewWithHeader
2.最后说一下为什么为什么用RecyclerView取代ListView。
用过ListView的都知道,在ListView中若要复用视图缓存,就要在getView()方法中手动判断convertView是否为空,若不为空则复用视图缓存,若为空则重新加载视图,而RecyclerView相当于对ListView的Adapter进行了再次封装,把ListView手动判断是否有缓存的代码封装到RecyclerView内部,使这部分逻辑不可见,我们只需要通过getItemCount()方法告诉RecyclerView有多少项数据,然后在onCreateViewHolder()中加载item布局实例化ViewHolder,然后在onBindViewHolder()中完成数据的绑定即可。
为RecyclerView的不同item项实现不同的布局(添加分类Header)的更多相关文章
- Android ListView item项 显示动画
		(1)使用LayoutAnimation 所谓的布局动画,其实就是为ViewGroup添加显示动画效果,主要用过LayoutAnimationController来控制实现.LayoutAnimati ... 
- listView  解决焦点冲突问题 item项和子控件之间的冲突
		listView 在item布局的顶级布局中设置 android:descendantFocusability="blocksDescendants"可以阻止子控件获取焦点 这样使 ... 
- ListView点击Item展开隐藏项(单项展开、多项展开、复杂布局时的展开处理)
		手机屏幕毕竟有限,当我们要显示较多数据时便不得不舍去一些次要信息.将主要信息优先显示,也使显示效果更加简洁美观.遇到类似的需求,我们使用最多的就是 ListView ,而假设每次点击一个 Item 都 ... 
- 【Android 界面效果49】RecyclerView高度随Item自适应
		编写RecyclerView.ItemDecoration时,在onDraw方法中,Drawable的高度等于RecyclerView的高度减去RecyclerView的上下padding. @Ove ... 
- Android解决RecyclerView中的item显示不全方案
		最近的项目中实现订单确定页面.需要使用ScrollView嵌套RecyclerView,当RecyclerView中的item数量比较多时,就会出现item只显示一部分数据,并没有将用户勾选的商品数量 ... 
- JavaScript中的内置对象-8--1.Array(数组)-Array构造函数;  数组的栈方法;  数组的转换方法;  数组的操作方法;  删除-插入-替换数组项;  ECMAScript为数组实例添加的两个位置方法;
		JavaScript内置对象-1Array(数组) 学习目标 1.掌握任何创建数组 2.掌握数值元素的读和写 3.掌握数组的length属性 如何创建数组 创建数组的基本方式有两种: 1.使用Arra ... 
- VS问题:该依赖项是由项目系统添加的,不能删除。
		该依赖项是由项目系统添加的,不能删除. 原因:是该项目添加对依赖项的引用时,不是直接引用的dll,而是通过“添加引用->项目”的方式引用的项目. 解决:删除“引用”目录下该依赖项的引用,然后通过 ... 
- Android RecyclerView 动画展开item显示详情
		stackoverflow上看到这个问题,答主给了个demo http://stackoverflow.com/questions/27446051/recyclerview-animate-item ... 
- ListBox之类控件的Item项显示对象的两个属性
		wpf项目中,ListBox绑定对象集合,ListBoxItem要显示对象的两个属性,例如:显示员工的工号和姓名. 之前我的做法是在Employee员工类中添加一个"NumAndName&q ... 
随机推荐
- vcf格式
			Variant Call Format(VCF)是一个用于存储基因序列突变信息的文本格式.表示单碱基突变, 插入/缺失, 拷贝数变异和结构变异等.BCF格式文件是VCF格式的二进制文件. CHROM ... 
- oracle 函数
			1.--dense_rank()分析函数(查找每个部门工资最高前三名员工信息) select * from (select deptno,ename,sal,dense_rank() over(par ... 
- Oracle时间戳(毫秒)转为Date
			1.SQL ) + TO_DATE('1970-01-01 08:00:00', 'YYYY-MM-DD HH:MI:SS'), 'YYYY-MM-DD HH:MI:SS') AS CDATE FRO ... 
- 如何运行Spark程序
			[hxsyl@CentOSMaster spark-2.0.2-bin-hadoop2.6]# ./bin/spark-submit --class org.apache.spark.examples ... 
- 一个将 footer 保持在底部的最好方法
			原文: Quick Tip: The Best Way To Make Sticky Footers 当你在布局网页时,有可能会遇到类似下面的这种情况 导致这一问题的原因是页面内容太少,无法将内容区域 ... 
- 在脚本中使用sudo命令,将密码保存在脚本中,不需要手动输入密码
			在脚本中使用sudo命令,将密码保存在脚本中,不需要手动输入密码. #!/bin/bash echo 'xxx密码xxx'|sudo -S service mysql start echo 'xxx密 ... 
- css悬浮
			<!DOCTYPE html><html><head> <meta charset="UTF-8"> <title&g ... 
- ASP.NET MVC4 URL传递汉字参数不能正确接收
			前两天写了个项目,在chrome上做的开发和测试. 拿给了产品,产品使用IE8.7.6进行测试的时候,发现很多报错.原因是URL里面的汉字在后台接收时显示的时乱码. 百度之~~ 最终解决方案, 在WE ... 
- 12月8日phpcms添加子栏目后的读取
			一个栏目下面如果没有子栏目,那么它调用的模板就是列表页模板(及list_为前缀的模板):如果一个栏目下面有子栏目,那么它调用的就是栏目首页模板(category_为前缀的模板). 所以,当你这个栏目添 ... 
- php数组操作集锦- 掌握了数组操作, 也就掌握了php
			参考下面的文章, 是很好的: http://www.cnblogs.com/staven/p/5142515.html http://pcwanli.blog.163.com/blog/static/ ... 
