最近在做一个应用的时候,需要为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)的更多相关文章

  1. Android ListView item项 显示动画

    (1)使用LayoutAnimation 所谓的布局动画,其实就是为ViewGroup添加显示动画效果,主要用过LayoutAnimationController来控制实现.LayoutAnimati ...

  2. listView 解决焦点冲突问题 item项和子控件之间的冲突

    listView 在item布局的顶级布局中设置 android:descendantFocusability="blocksDescendants"可以阻止子控件获取焦点 这样使 ...

  3. ListView点击Item展开隐藏项(单项展开、多项展开、复杂布局时的展开处理)

    手机屏幕毕竟有限,当我们要显示较多数据时便不得不舍去一些次要信息.将主要信息优先显示,也使显示效果更加简洁美观.遇到类似的需求,我们使用最多的就是 ListView ,而假设每次点击一个 Item 都 ...

  4. 【Android 界面效果49】RecyclerView高度随Item自适应

    编写RecyclerView.ItemDecoration时,在onDraw方法中,Drawable的高度等于RecyclerView的高度减去RecyclerView的上下padding. @Ove ...

  5. Android解决RecyclerView中的item显示不全方案

    最近的项目中实现订单确定页面.需要使用ScrollView嵌套RecyclerView,当RecyclerView中的item数量比较多时,就会出现item只显示一部分数据,并没有将用户勾选的商品数量 ...

  6. JavaScript中的内置对象-8--1.Array(数组)-Array构造函数; 数组的栈方法; 数组的转换方法; 数组的操作方法; 删除-插入-替换数组项; ECMAScript为数组实例添加的两个位置方法;

    JavaScript内置对象-1Array(数组) 学习目标 1.掌握任何创建数组 2.掌握数值元素的读和写 3.掌握数组的length属性 如何创建数组 创建数组的基本方式有两种: 1.使用Arra ...

  7. VS问题:该依赖项是由项目系统添加的,不能删除。

    该依赖项是由项目系统添加的,不能删除. 原因:是该项目添加对依赖项的引用时,不是直接引用的dll,而是通过“添加引用->项目”的方式引用的项目. 解决:删除“引用”目录下该依赖项的引用,然后通过 ...

  8. Android RecyclerView 动画展开item显示详情

    stackoverflow上看到这个问题,答主给了个demo http://stackoverflow.com/questions/27446051/recyclerview-animate-item ...

  9. ListBox之类控件的Item项显示对象的两个属性

    wpf项目中,ListBox绑定对象集合,ListBoxItem要显示对象的两个属性,例如:显示员工的工号和姓名. 之前我的做法是在Employee员工类中添加一个"NumAndName&q ...

随机推荐

  1. java-读取xml

    1.使用w3c.document /** * 测试 * */ public static void testReadLabel() { String path = "C:\\Users\\h ...

  2. Apache报错信息之通常每个套接字地址(协议/网络地址/端口)只允许使用一次(could not bind to address 0.0.0.0:80)

    我们常常在执行 httpd –k restart 重启Apache时报错提示: (OS 10048)通常每个套接字地址(协议/网络地址/端口)只允许使用一次.  : AH00072: make_soc ...

  3. 【BZOJ-3881】Divljak AC自动机fail树 + 树链剖分+ 树状数组 + DFS序

    3881: [Coci2015]Divljak Time Limit: 20 Sec  Memory Limit: 768 MBSubmit: 508  Solved: 158[Submit][Sta ...

  4. BZOJ-2127-happiness(最小割)

    2127: happiness(题解) Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1806  Solved: 875 Description 高一 ...

  5. PHP编码规范PSR-2

    .note-content { font-family: "Helvetica Neue", Arial, "Hiragino Sans GB", STHeit ...

  6. Linux 文件压缩与归档

    .note-content { font-family: "Helvetica Neue", Arial, "Hiragino Sans GB", STHeit ...

  7. 在windows下使用linux命令,GnuWin32的使用.

    http://sourceforge.net/projects/getgnuwin32 使用过linxu的伙计估计都会喜欢上linux各种各样强大的命令如:grep, sed,awk,diff和pat ...

  8. 通过SmartGit把java maven项目传到码云

    一.首先先在码云上新建一个项目 二.复制项目的链接 三.打开SmartGit,点击clone 4.把复制的项目链接粘上去 5.然后点两次next,选择一个路径,finish 6.打开刚刚选择的路径,我 ...

  9. ig WebDataGrid清除选中行

    EnableViewState="false" gridID.Behaviors.Selection.SelectedRows.Clear();

  10. Nginx笔记

    基础篇 关于Nginx Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器.最早由俄罗斯的程序设计师Igor Sysoev所开发,并在一个BSD-like ...