RecyclerView添加addHeader和addFooter方法
来源:互联网 发布:淘宝哪家女童卖的好 编辑:程序博客网 时间:2024/06/05 07:00
在新版本的android系统中RecyclerView作为ListView的优化版本,封装了ViewHolder,这样就可以更加方便的使用这个控件。但是相比较ListView,RecyclerView没有提供相应的addHeaderView和addFooterView方法,我们知道在一些下拉控件的实现中,都是设置了headerView或者是footerView,然后不断的设置padding来实现的。那既然RecyclerView没有addHeaderView和addFooterView这些方法,那么是不是就不能实现下拉刷新这样的功能了呢?当然不是。下面就带大家实现一个简易的实现addHeaderView和addFooterView的方法。
我们知道像需要适配器的这些控件,它们的数据都是通过Adapter的提供的。那么我们就着手改造我们的Adapter。首先我们创建一个自定义的Adapter类继承RecyclerView.Adapter
public class HeaderRecyclerViewAdapter extends RecyclerView.Adapter<HeaderRecyclerViewAdapter .HeaderViewHolder> { //header view type的开始值 private final int RECYCLER_HEADER_TYPE_BASE = 0xff11; //footer view type的开始值 private final int RECYCLER_FOOTER_TYPE_BASE = 0xff22; //header和footer的id值 private final int RECYCLER_HEADER_FOOTER_ID = -1; //用来存放所有的header view的信息 private List<FixedInfo> mHeaders = new ArrayList<>(); //用来存放所有的footer view的信息 private List<FixedInfo> mFooters = new ArrayList<>(); //保存使用默认的RecyclerView.Adapter创建的adapter的值,这个值必须获取到 private RecyclerView.Adapter mAdapter = null; public HeaderRecyclerViewAdapter() { } public HeaderRecyclerViewAdapter(RecyclerView.Adapter adapter) { this.mAdapter = adapter; } public void setAdapter(RecyclerView.Adapter adapter) { this.mAdapter = adapter; }
我们创建一个HeaderRecyclerViewAdapter类用来包装我们原始的RecyclerView.Adapter类,mAdpter就是对这个原始类的应用。同样创建了两个ArrayList用来保存我们的Headers和footers,这里面有一个FixedInfo类,这个类是干嘛的呢?
//用来保存footer和headers的信息 private class FixedInfo { public View view; public int type; }
这个类比较简单,view保存我们设置的view,type用来保存我们view的type信息,可以通过type信息识别我们的header和footer。
public void addHeader(View view) { FixedInfo info = new FixedInfo(); info.view = view; info.type = RECYCLER_HEADER_TYPE_BASE + mHeaders.size(); mHeaders.add(info); } public void addFooter(View view) { FixedInfo info = new FixedInfo(); info.view = view; info.type = RECYCLER_FOOTER_TYPE_BASE + mFooters.size(); mFooters.add(info); }
可以看到,每次addHeader或者是addFooter的时候,都通过一个唯一的type信息来区别这个view。
@Override public long getItemId(int position) { int headerCount = getHeaderSize(); if (mAdapter != null && position >= headerCount) { int adjPosition = position - headerCount; return mAdapter.getItemId(adjPosition); } return RECYCLER_HEADER_FOOTER_ID; }
我们需要重新getItemId()方法,如果是header或者是footer的话,直接返回我们定义的特殊值 RECYCLER_HEADER_FOOTER_ID。如果是adapter中的数据则返回adapter中的相同方法。
@Override public int getItemViewType(int position) { if (mAdapter == null) { throw new IllegalStateException("must have a adapter"); } int headerCount = getHeaderSize(); int adapterCount = mAdapter.getItemCount(); if (position < headerCount) { return mHeaders.get(position).type; } else if (position >= (headerCount + adapterCount)) { return mFooters.get(position - headerCount - adapterCount).type; } else { int adjPosition = position - headerCount; return mAdapter.getItemViewType(adjPosition); } }
getItemViewType()是我们必须重写的方法,在这个方法中,我们会标识每一个Header和Footer的viewType。
@Override public HeaderViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (isHeaderView(viewType)) { int delta = viewType - RECYCLER_HEADER_TYPE_BASE; View view = mHeaders.get(delta).view; return new HeaderViewHolder(view); } if (isFooterView(viewType)) { int delta = viewType - RECYCLER_FOOTER_TYPE_BASE; View view = mFooters.get(delta).view; return new HeaderViewHolder(view); } return (HeaderViewHolder) mAdapter.onCreateViewHolder(parent,viewType); } @Override public void onBindViewHolder(HeaderViewHolder holder, int position) { int headerCount = getHeaderSize(); if (mAdapter != null && position >= headerCount) { int adapterCount = mAdapter.getItemCount(); int adjPosition = position - headerCount; if (adjPosition >= 0 && adjPosition < adapterCount) { mAdapter.onBindViewHolder(holder, adjPosition); } } }
最主要的地方来了,在onCreateViewHolder中,我们需要判断当前的viewType是header的还是footer的,如果是header的或者footer的,我们需要算出这个viewtype所对应的view,用这个view来返回HeaderViewHolder。而在onBindViewHolder()方法中,我们只需要定位到属于adapter中的数据就好,然后返回对应的方法即可。完整的代码如下:
package com.gearmotion.app.mylibrary; import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.ViewGroup; import java.util.ArrayList; import java.util.List; /** * Created by Charles on 2016/3/21. */ public class HeaderRecyclerViewAdapter extends RecyclerView.Adapter<HeaderRecyclerViewAdapter .HeaderViewHolder> { //header view type的开始值 private final int RECYCLER_HEADER_TYPE_BASE = 0xff11; //footer view type的开始值 private final int RECYCLER_FOOTER_TYPE_BASE = 0xff22; //header和footer的id值 private final int RECYCLER_HEADER_FOOTER_ID = -1; //用来存放所有的header view的信息 private List<FixedInfo> mHeaders = new ArrayList<>(); //用来存放所有的footer view的信息 private List<FixedInfo> mFooters = new ArrayList<>(); //保存使用默认的RecyclerView.Adapter创建的adapter的值,这个值必须获取到 private RecyclerView.Adapter mAdapter = null; public HeaderRecyclerViewAdapter() { } public HeaderRecyclerViewAdapter(RecyclerView.Adapter adapter) { this.mAdapter = adapter; } public void setAdapter(RecyclerView.Adapter adapter) { this.mAdapter = adapter; } @Override public HeaderViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (isHeaderView(viewType)) { int delta = viewType - RECYCLER_HEADER_TYPE_BASE; View view = mHeaders.get(delta).view; return new HeaderViewHolder(view); } if (isFooterView(viewType)) { int delta = viewType - RECYCLER_FOOTER_TYPE_BASE; View view = mFooters.get(delta).view; return new HeaderViewHolder(view); } return (HeaderViewHolder) mAdapter.onCreateViewHolder(parent,viewType); } @Override public void onBindViewHolder(HeaderViewHolder holder, int position) { int headerCount = getHeaderSize(); if (mAdapter != null && position >= headerCount) { int adapterCount = mAdapter.getItemCount(); int adjPosition = position - headerCount; if (adjPosition >= 0 && adjPosition < adapterCount) { mAdapter.onBindViewHolder(holder, adjPosition); } } } @Override public int getItemCount() { if (mAdapter != null) { return mHeaders.size() + mAdapter.getItemCount() + mFooters.size(); } else { return mHeaders.size() + mFooters.size(); } } @Override public int getItemViewType(int position) { if (mAdapter == null) { throw new IllegalStateException("must have a adapter"); } int headerCount = getHeaderSize(); int adapterCount = mAdapter.getItemCount(); if (position < headerCount) { return mHeaders.get(position).type; } else if (position >= (headerCount + adapterCount)) { return mFooters.get(position - headerCount - adapterCount).type; } else { int adjPosition = position - headerCount; return mAdapter.getItemViewType(adjPosition); } } @Override public long getItemId(int position) { int headerCount = getHeaderSize(); if (mAdapter != null && position >= headerCount) { int adjPosition = position - headerCount; return mAdapter.getItemId(adjPosition); } return RECYCLER_HEADER_FOOTER_ID; } public void addHeader(View view) { FixedInfo info = new FixedInfo(); info.view = view; info.type = RECYCLER_HEADER_TYPE_BASE + mHeaders.size(); mHeaders.add(info); } public void addFooter(View view) { FixedInfo info = new FixedInfo(); info.view = view; info.type = RECYCLER_FOOTER_TYPE_BASE + mFooters.size(); mFooters.add(info); } public int getHeaderSize() { return mHeaders.size(); } public int getFooterSize() { return mFooters.size(); } private boolean isHeaderView(int type) { int delta = type - RECYCLER_HEADER_TYPE_BASE; return delta >= 0 && delta < mHeaders.size(); } private boolean isFooterView(int type) { int delta = type - RECYCLER_FOOTER_TYPE_BASE; return delta >= 0 && delta < mFooters.size(); } //用来保存footer和headers的信息 private class FixedInfo { public View view; public int type; } //自定义的viewholder public static class HeaderViewHolder extends RecyclerView.ViewHolder { public HeaderViewHolder(android.view.View itemView) { super(itemView); } } }
最后我们在使用的时候将原始创建的adapter传递给HeaderRecyclerViewAdapter即可。
package com.gearmotion.app.headerrecyclerviewmotion; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.text.Layout; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import com.gearmotion.app.mylibrary.HeaderRecyclerViewAdapter; public class MainActivity extends AppCompatActivity { private RecyclerView mRecyclerView; private LayoutInflater mInflater; private String[] mDatas = new String[]{"title1", "title2", "title3", "title4", "title5", "title6"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mInflater = LayoutInflater.from(this); mRecyclerView = (RecyclerView) this.findViewById(R.id.recyclerview); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); CustomAdapter tmpAdapter = new CustomAdapter(); HeaderRecyclerViewAdapter mAdapter = new HeaderRecyclerViewAdapter(tmpAdapter); mAdapter.addHeader(createView("head1")); mAdapter.addHeader(createView("head2")); mAdapter.addHeader(createView("head3")); mAdapter.addFooter(createView("foot1")); mAdapter.addFooter(createView("foot2")); mAdapter.addFooter(createView("foot3")); mRecyclerView.setAdapter(mAdapter); } private View createView(String title) { TextView tv = new TextView(this); tv.setText(title); tv.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 70)); tv.setGravity(Gravity.CENTER); return tv; } public class CustomAdapter extends RecyclerView.Adapter<CustomViewHolder> { @Override public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View root = mInflater.inflate(R.layout.item, null); return new CustomViewHolder(root); } @Override public void onBindViewHolder(CustomViewHolder holder, int position) { holder.textView.setText(mDatas[position]); } @Override public int getItemCount() { return mDatas.length; } } public class CustomViewHolder extends HeaderRecyclerViewAdapter.HeaderViewHolder { public TextView textView; public CustomViewHolder(View itemView) { super(itemView); textView = (TextView) itemView.findViewById(R.id.itemtextview); } } }
结果如下:
代码地址如下:https://github.com/summerpxy/HeaderRecyclerViewAdapter.git
- RecyclerView添加addHeader和addFooter方法
- Listview添加头和尾,addHeader,addFooter,以及利用尾显示更新过程
- Android 4.4以下ListView addHeader和addFooter放在setAdapter之后导致异常的原因分析和解决
- RecyclerView添加Header和Footer的方法
- 使用RecyclerView添加Header和Footer的方法
- 使用RecyclerView添加Header和Footer的方法
- RecyclerView添加Header和Footer
- RecyclerView添加头部和底部
- RecyclerView添加Header和Footer
- RecyclerView添加Header和Footer
- RecyclerView添加header和footer
- RecyclerView添加header和footer
- RecyclerView添加头部和尾部
- RecyclerView添加HeaderView和FooterView
- RecyclerView添加headerview和footview
- RecyclerView添加HeaderView和FooterView
- RecyclerView添加HeaderView和FooterView
- RecyclerView 添加headerView 和 footerView
- 杭电2845 Beans 不连续的最大字段和
- 《世冷》进行时
- virtual 虚函数的demo
- java 反斜杠转义
- python系列之 RabbitMQ - RPC
- RecyclerView添加addHeader和addFooter方法
- 将 JAR 转为 EXE – exe4j 的使用教程(第一期)
- PHP中的数据类型转换和类型检测
- Java面向对象06-多态,内部类
- Matlab 未找到支持的编译器或 SDK 解决方法归纳
- 域渗透——Skeleton Key
- Ocx 控件添加函数接口,注册控件
- 创建数据库的顺序
- java语言程序设计第十版(Introduce to java 10th) 课后习题 chapter6-32