为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 ...
随机推荐
- ACM提交结果简介
如果你看到红色的"Accepted",那么,恭喜你,你已经成功的解决了该问题! 如果你收到的是如下的信息,则还需要继续检查你的程序: Wrong Answer (WA) : 输出结 ...
- C# 常用代码
学习备忘 1.判断程序是否运行 static void Main() { bool canCreateNew; System.Threading.Mutex myownmutex = new Syst ...
- Linux下如何查找.sh后缀的文件
find / -name *.sh或locate *.shfind 与locate的区别:locate 配合数据库查看文件位置 find 实际搜寻硬盘查询文件名称
- Unity Animator动画状态机 深入理解(三)二维混合树
介绍二维之前,先说说一维吧~ 这个是通过旋转角度速度快慢来表现身体的大转和中转~ 通过一个-133~133的数值来进行控制. 注:后面的那个对钩是镜像的意思. 其实二维混合树并没有想象中的那么难.先来 ...
- centos手动编译安装apache、php、mysql
64位centos 5.5手动安装lamp,要求curl.json.pdo_mysql.gd,记录如下. centos 5.4.5.5.5.6的内核都是2.6.18,都可以安装php 5.3. 卸载旧 ...
- HibernateSessionFactory建立-使用ThreadLocal
立即加载还是延迟加载必须要连接数据库的,而在Java中连接数据库是依赖java.sql.Connection,在hibernate中session就是Connection的一层高级封装,一个sessi ...
- HTTP Cache
最近在学习HTTP协议,看的书籍是<HTTP权威指南>,这本书讲的很不错,细节都讲的很透彻,虽然书本比较厚,因为讲的通俗易懂,所以比较有意思并不觉得枯燥.下面是读书后做的读书笔记. [图片 ...
- python笔记1-转义字符
print(r'dd"e"f')print(r'dd'e'f')print(r"dd"e"f")print(r"dd'e'f&qu ...
- window.onload 和 DOMContentLoaded区别及如何判断dom是否加载完毕
http://blog.allenm.me/2010/02/window-onload-和-domcontentloaded/ 其中使用IE不支持DOMContentLoaded,那么判断IE是否加载 ...
- SharePoint Claim base authentication EnsureUser 不带claim(i:0#.w|)user Failed
环境信息: 带有Form base authentication(FBA).Active Directory Federation Services(ADFS).以及windows Authentic ...