RecyclerView添加头部和底部视图的实现
ListView是有addHeaderView和 addFooterView两个方法的.
但是作为官方推荐的ListView的升级版RecyclerView缺无法实现这两个方法。
那么如果使用RecyclerView实现这两个方法的效果该怎么做呢?
网上查询了很久,试过各种各样的实现方式,终于让我发现一个还不错的实现方法,那么就给大家推荐一下。
项目地址(别人写的,非博主的)https://github.com/jczmdeveloper/XCRecyclerView
我看了下这个源码,很简单,即写了一个继承RecyclerView的控件,自己实现addHeaderView和addFooterView两个方法
package com.xqx.com.recyclerviewheaderdemo; import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup; import java.util.ArrayList;
import java.util.List; public class XCRecyclerView extends RecyclerView{ private ArrayList<View> mHeaderViews = new ArrayList<>();
private ArrayList<View> mFooterViews = new ArrayList<>();
private RecyclerView.Adapter mAdapter;
private RecyclerView.Adapter mWrapAdapter;
private static final int TYPE_HEADER = -;
private static final int TYPE_FOOTER = -;
private static final int TYPE_LIST_ITEM = - ;
public XCRecyclerView(Context context) {
this(context, null);
}
public XCRecyclerView(Context context, AttributeSet attrs) {
this(context, attrs, );
}
public XCRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context){ } @Override
public void setAdapter(Adapter adapter) {
mAdapter = adapter;
mWrapAdapter = new WrapAdapter(mHeaderViews, mFooterViews, adapter);
super.setAdapter(mWrapAdapter);
mAdapter.registerAdapterDataObserver(mDataObserver);
}
public void addHeaderView(View view){
mHeaderViews.clear();
mHeaderViews.add(view);
}
public void addFooterView(View view){
mFooterViews.clear();
mFooterViews.add(view);
}
public int getHeaderViewsCount(){
return mHeaderViews.size();
}
public int getFooterViewsCount(){
return mFooterViews.size();
}
private final RecyclerView.AdapterDataObserver mDataObserver = new RecyclerView.AdapterDataObserver() {
@Override
public void onChanged() {
mWrapAdapter.notifyDataSetChanged();
} @Override
public void onItemRangeChanged(int positionStart, int itemCount) {
mWrapAdapter.notifyItemRangeChanged(positionStart, itemCount);
} // @Override
// public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
// mWrapAdapter.notifyItemRangeChanged(positionStart, itemCount, payload);
// } @Override
public void onItemRangeInserted(int positionStart, int itemCount) {
mWrapAdapter.notifyItemRangeInserted(positionStart, itemCount);
} @Override
public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
mWrapAdapter.notifyItemMoved(fromPosition, toPosition);
} @Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
mWrapAdapter.notifyItemRangeRemoved(positionStart, itemCount);
}
};
private class WrapAdapter extends RecyclerView.Adapter<ViewHolder>{ private Adapter mAdapter;
private List<View> mHeaderViews;
private List<View> mFooterViews;
public WrapAdapter(List<View> headerViews,List<View> footerViews,Adapter adapter){
this.mAdapter = adapter;
this.mHeaderViews = headerViews;
this.mFooterViews = footerViews;
} public int getHeaderCount(){
return this.mHeaderViews.size();
}
public int getFooterCount(){
return this.mFooterViews.size();
}
public boolean isHeader(int position){
return position >= && position < this.mHeaderViews.size();
}
public boolean isFooter(int position){
return position < getItemCount() && position >= getItemCount() - this.mFooterViews.size();
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType == TYPE_HEADER){
return new CustomViewHolder(this.mHeaderViews.get());
}else if(viewType == TYPE_FOOTER){
return new CustomViewHolder(this.mFooterViews.get());
}else{
return this.mAdapter.onCreateViewHolder(parent,viewType);
}
} @Override
public void onBindViewHolder(ViewHolder holder, int position) {
if(isHeader(position)) return;
if(isFooter(position)) return;
int rePosition = position - getHeaderCount();
int itemCount = this.mAdapter.getItemCount();
if(this.mAdapter != null){
if(rePosition < itemCount){
Log.v("czm","rePosition/itemCount="+rePosition+"/"+itemCount);
this.mAdapter.onBindViewHolder(holder,rePosition);
return;
}
}
}
@Override
public long getItemId(int position) {
if (this.mAdapter != null && position >= getHeaderCount()) {
int rePosition = position - getHeaderCount();
int itemCount = this.mAdapter.getItemCount();
if (rePosition < itemCount) {
return this.mAdapter.getItemId(rePosition);
}
}
return -;
}
@Override
public int getItemViewType(int position) {
if(isHeader(position)){
return TYPE_HEADER;
}
if(isFooter(position)){
return TYPE_FOOTER;
}
int rePosition = position - getHeaderCount();
int itemCount = this.mAdapter.getItemCount();
if(rePosition < itemCount){
return this.mAdapter.getItemViewType(position);
}
return TYPE_LIST_ITEM;
}
@Override
public int getItemCount() {
if(this.mAdapter != null){
return getHeaderCount() + getFooterCount() + this.mAdapter.getItemCount();
}else{
return getHeaderCount() + getFooterCount();
}
} @Override
public void registerAdapterDataObserver(AdapterDataObserver observer) {
if(this.mAdapter != null){
this.mAdapter.registerAdapterDataObserver(observer);
}
} @Override
public void unregisterAdapterDataObserver(AdapterDataObserver observer) {
if(this.mAdapter != null){
this.mAdapter.unregisterAdapterDataObserver(observer);
}
} private class CustomViewHolder extends ViewHolder{ public CustomViewHolder(View itemView) {
super(itemView);
}
}
}
}
XCRecyclerView
使用方法github里也写的清清楚楚的
private MyAdapter mAdapter;
private XCRecyclerView mRecyclerView;
private List<String> mData;
private View mHeaderView;
private View mFooterView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mData = new ArrayList<String>();
for(int i = ; i < ;i++){
mData.add("item_" + i);
}
mAdapter = new MyAdapter(mData);
mRecyclerView = (XCRecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mHeaderView = LayoutInflater.from(this).inflate(R.layout.layout_header,mRecyclerView,false);
mFooterView = LayoutInflater.from(this).inflate(R.layout.layout_footer,mRecyclerView,false);
mRecyclerView.addHeaderView(mHeaderView);
mRecyclerView.addFooterView(mFooterView);
mRecyclerView.setAdapter(mAdapter);
}
注意点:
addHeaderView之后 列表的数据坐标即相应发生变化!即addHeadView一次,列表第一个数据的下坐标+1(0-->1)
adapter.notifyItemChanged();等方法的坐标类似,都要相应的变化。
比如你addHeadView()一次
那么你想更新列表第4个列表项的视图,则adapter.notifyItemChanged(3+1); 多加1 headView也算一个列表项。
RecyclerView添加头部和底部视图的实现的更多相关文章
- RecyclerView添加头部和底部视图的实现方法
引用-- http://www.zhimengzhe.com/Androidkaifa/15072.html 在天下货crm----签到---签到记录中有使用
- 可添加头部尾部RecyclerView,很帅哦~
WrapRecyclerView 是一个可以添加头部和尾部的RecyclerView,并且提供了一个 WrapAdapter, 它可以让你轻松为 RecyclerView 添加头部和尾部. 示例中 ...
- Android 5.X新特性之为RecyclerView添加HeaderView和FooterView
上一节我们讲到了 Android 5.X新特性之RecyclerView基本解析及无限复用 相信大家也应该熟悉了RecyclerView的基本使用,这一节我们来学习下,为RecyclerView添加H ...
- RecyclerView--添加头部和底部
1.先构建WrapRecyclerAdapter /** * Description: 可以添加头部和底部的Adapter */ public class WrapRecyclerAdapter ex ...
- Android RecyclerView添加Header头部
Android RecyclerView添加Header头部 Android RecyclerView不像以前的ListView那样直接添加头部,如果要给RecyclerView增加头部,则需要 ...
- Android 5.X新特性之为RecyclerView添加下拉刷新和上拉加载及SwipeRefreshLayout实现原理
RecyclerView已经写过两篇文章了,分别是Android 5.X新特性之RecyclerView基本解析及无限复用 和 Android 5.X新特性之为RecyclerView添加Header ...
- RecyclerView添加Header的正确方式
原文链接:http://blog.csdn.net/qibin0506/article/details/49716795 看了一下博客目录,已经有好几篇博客是关于RecyclerView的,不过对于这 ...
- HTML5 开发APP(头部和底部选项卡)
我们开发app有一定固定的样式,比如头部和底部选项卡部分就是公共部分就比如我在做的app进来的主页面就像图片显示的那样 我们该怎么实现呢,实现我们应该建一个主页面index.html,然后建五个子页面 ...
- ionic-CSS:ionic 头部与底部
ylbtech-ionic-CSS:ionic 头部与底部 1.返回顶部 1. ionic 头部与底部 Header(头部) Header是固定在屏幕顶部的组件,可以包如标题和左右的功能按钮. ion ...
随机推荐
- java攻城师之路(Android篇)--搭建开发环境、拨打电话、发送短信、布局例子
一.搭建开发环境 1.所需资源 JDK6以上 Eclipse3.6以上 SDK17, 2.3.3 ADT17 2.安装注意事项 不要使用中文路径 如果模拟器默认路径包含中文, 可以设置android_ ...
- C# 事件和委托
相信大家在面试的时候会经常问到事件和委托的区别,为什么.net中需要事件和委托这样类似的问题吧,对于一些初学者来说可平时用的过程中也不知道为什么, 只知道这样用,而对于其中的实现机制不是很清楚, 所以 ...
- SQL中的连接查询及其优化原则
连接查询是SQL的主要任务,只有很好的掌握了连接查询及其优化方法才算是掌握了SQL的精髓所在.最近在面试中遇到了有关连接查询的问题,感觉回答的不是很好,总结一下. 具体示例请参考:http://www ...
- 基于openssl的单向和双向认证
1.前言 最近工作涉及到https,需要修改nginx的openssl模块,引入keyless方案.关于keyless可以参考CloudFlare的官方博客: https://blog.cloudfl ...
- SystemTap知识(二)
Unbuntu安装systemtap: http://www.cnblogs.com/hdflzh/archive/2012/07/25/2608910.html 1 更新源到http://mirro ...
- Angular系列----AngularJS入门教程04:迭代器过滤(转载)
我们在上一步做了很多基础性的训练,所以现在我们可以来做一些简单的事情喽.我们要加入全文检索功能(没错,这个真的非常简单!).同时,我们也会写一个端到端测试,因为一个好的端到端测试可以帮上很大忙.它监视 ...
- 重构第14天 分离职责(Break Responsibilities)
理解:面向对象的五大特征: SOLID,其中S就是职责单一原则.分离职责指当一个类有许多职责时,将部分职责分离到独立的类中,这样也符合面向对象的五大特征之一的单一职责原则,同时也可以使代码的结构更加清 ...
- UnityShader快速上手指南(四)
简介 由于其他项目中断了几天更新,继续~~ 这一篇主要是讲光照的(包含漫反射和高光以及多光源的处理) 还是先来看看具体效果(多光源后面单独展示) 有了基本的光照处理之后越来越有立体感了有不有 ╮(╯▽ ...
- Dev TreeList设置焦点失败解决方法
问题描述 对TreeList初始化之后,设置treelist的焦点节点时,发现每次初始化控件的时不能正确的绑定焦点节点,第二次点开treelist的时候才会正常的设置目标节点为焦点节点. 截图 解决方 ...
- [CLR via C#]14. 字符、字符串和文本处理
一.字符 在.NET Framewole中,字符总是表示成16位Unicode代码值,这简化了国际化应用程序的开发. 每个字符都表示成System.Char结构(一个值类型) 的一个实例.System ...