基于前面的博文给RecyclerView添加Header,给RecyclerView添加多个Header
通过上节的内容,我们知道了给RecyclerView(GridLayoutManager)添加Header的方法
1.首先初始化了一个HeaderView用于下拉刷新使用并且将这个下拉刷新的布局添加到头布局
/**
* 初始化头布局
*/
private void initHeaderView() {
header = RecyclerViewHeader.fromXml(getContext(), R.layout.refresh_header);
// 添加HeaderView
this.addHeaderView(header);
tvTitle = (TextView) header.findViewById(R.id.tv_title);
tvTime = (TextView) header.findViewById(R.id.tv_time);
ivArrow = (ImageView) header.findViewById(R.id.iv_arr);
pbProgress = (ProgressBar) header.findViewById(R.id.pb_progress);
header.measure(0, 0);
headerHeight = header.getMeasuredHeight();
// 隐藏头布局
header.setPadding(0, -headerHeight, 0, 0); // 负的值就能够让控件向上移动了
initArrowAnim(); // 初始化箭头动画
// 更新最后刷新的时间
tvTime.setText("最后刷新时间" + getCurrentTime());
}
2.在添加头布局的时候,首先先是将原先拥有的HeaderView全部都清除了,接着再将需要添加的View添加进去,值得注意的是,就是这个clear操作导致了我们自己自定义的addHeaderView方法只能够添加一个HeaderView
/**
* 添加头布局
*
* @param view
*/
public void addHeaderView(View view) {
mHeaderViews.clear();
mHeaderViews.add(view);
if (mAdapter != null) {
if (!(mAdapter instanceof RecyclerWrapAdapter)) {
mAdapter = new RecyclerWrapAdapter(mHeaderViews, mFooterViews, mAdapter);
mAdapter.notifyDataSetChanged();
}
}
}
3.在addHeaderView中实例化RecyclerWrapAdapter,这个RecyclerWrapAdapter就是整个自定义RecyclerView中最核心的部分,我们挑选最重要的地方来看
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == RecyclerView.INVALID_TYPE) {
return new HeaderViewHolder(mHeaderViews.get(0)); // 将第一个HeaderView封装
} else if (viewType == RecyclerView.INVALID_TYPE - 2) {
return new HeaderViewHolder(mFooterViews.get(0)); // 将FooterView封装
}
return mAdapter.onCreateViewHolder(parent, viewType);
}
@Override
public int getItemViewType(int position) {
if (mCurrentPosition == -1) {
mCurrentPosition = position; // 这是第一个HeaderView
}
int numHeaders = getHeadersCount();
if (position < numHeaders) {
return RecyclerView.INVALID_TYPE; // 这是第一个HeaderView所占用的空间
}
int adjPosition = position - numHeaders;
int adapterCount = 0;
if (mAdapter != null) {
adapterCount = mAdapter.getItemCount();
if (adjPosition < adapterCount) {
return mAdapter.getItemViewType(adjPosition);
}
}
return RecyclerView.INVALID_TYPE - 2; // 说明是Footer的所占用的空间
}
这两段代码就是最重要的地方,我们会发现,getViewType返回的值被引用成了onCreateViewHolder的参数所以我们如果想要添加多个HeaderView就需要在这里入手。
添加多个HeaderView的具体方法:
1.我们将RecyclerWrapAdapter中的核心方法修改下,修改成可以添加两个HeaderView的
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == RecyclerView.INVALID_TYPE) {
return new HeaderViewHolder(mHeaderViews.get(0)); // 将第一个HeaderView封装
} else if(viewType == RecyclerView.INVALID_TYPE - 1){
return new HeaderViewHolder(mHeaderViews.get(1)); // 将第二个HeaderView封装
} else if (viewType == RecyclerView.INVALID_TYPE - 2) {
return new HeaderViewHolder(mFooterViews.get(0)); // 将FooterView封装
}
return mAdapter.onCreateViewHolder(parent, viewType);
}
@Override
public int getItemViewType(int position) {
if (mCurrentPosition == -1) {
mCurrentPosition = position; // 这是第一个HeaderView
}
int numHeaders = getHeadersCount();
if (position < numHeaders) {
if (position != mCurrentPosition) { // 这是第二个HeaderView
return RecyclerView.INVALID_TYPE - 1; // 这是第二个HeaderView所占用的空间
}
return RecyclerView.INVALID_TYPE; // 这是第一个HeaderView所占用的空间
}
int adjPosition = position - numHeaders;
int adapterCount = 0;
if (mAdapter != null) {
adapterCount = mAdapter.getItemCount();
if (adjPosition < adapterCount) {
return mAdapter.getItemViewType(adjPosition);
}
}
return RecyclerView.INVALID_TYPE - 2; // 说明是Footer的所占用的空间
}
2.光在RecyclerWrapAdapter里改还不够,还记得addHeaderView方法的第一行代码mHeaderView.clear();这段代码就从源头上将添加多个HeaderVIew的源头给堵住了,所以,如果我们需要添加多个HeaderView就需要将这段代码删掉。
// mHeaderViews.clear();
然后再运行下,就可以发现两个HeaderView就成功添加了!
下面附上RecyclerWrapAdapter 的源码:
package com.deltalab.urecommend.adapter.friend_pager;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import com.deltalab.urecommend.adapter.base.WrapperAdapter;
import java.util.ArrayList;
/**
* Created by asus on 2016/10/14.
* 添加了headerView和footerView的布局适配器
* 模仿ListView里addHeader的HeaderViewListAdapter
*
* @author Administrator
* @time 2016/10/14 16:54
*/
public class RecyclerWrapAdapter extends RecyclerView.Adapter implements WrapperAdapter {
private RecyclerView.Adapter mAdapter;
private ArrayList<View> mHeaderViews;
private ArrayList<View> mFooterViews;
private int mCurrentPosition = -1;
static final ArrayList<View> EMPTY_INFO_LIST = new ArrayList<View>();
public RecyclerWrapAdapter(ArrayList<View> mHeaderViews, ArrayList<View> mFooterViews,
RecyclerView.Adapter mAdapter) {
this.mAdapter = mAdapter;
if (mHeaderViews == null) {
this.mHeaderViews = EMPTY_INFO_LIST;
} else {
this.mHeaderViews = mHeaderViews;
}
if (mFooterViews == null) {
this.mFooterViews = EMPTY_INFO_LIST;
} else {
this.mFooterViews = mFooterViews;
}
}
/**
* 获取头布局的数量
*
* @return
*/
public int getHeadersCount() {
return mHeaderViews.size();
}
public int getFootersCount() {
return mFooterViews.size();
}
/**
* 把View直接封装在ViewHolder中,然后我们面向的是ViewHolder这个实例
* 如果是Header、Footer则使用HeaderViewHolder封装
* 如果是其他的就不变
*
* @param parent
* @param viewType
* @return
*/
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == RecyclerView.INVALID_TYPE) {
return new HeaderViewHolder(mHeaderViews.get(0)); // 将第一个HeaderView封装
} else if(viewType == RecyclerView.INVALID_TYPE - 1){
return new HeaderViewHolder(mHeaderViews.get(1)); // 将第二个HeaderView封装
} else if (viewType == RecyclerView.INVALID_TYPE - 2) {
return new HeaderViewHolder(mFooterViews.get(0)); // 将FooterView封装
}
return mAdapter.onCreateViewHolder(parent, viewType);
}
/**
* 用于适配渲染数据到View中。方法提供给你了一个viewHolder,而不是原来的convertView。
*
* @param holder
* @param position
*/
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
// Header
int numHeaders = getHeadersCount();
if (position < numHeaders) {
return;
}
// Adapter
int adjPosition = position - numHeaders;
int adapterCount = 0;
if (mAdapter != null) {
adapterCount = mAdapter.getItemCount();
if (adjPosition < adapterCount) {
mAdapter.onBindViewHolder(holder, adjPosition);
return;
}
}
}
/**
* 将Header、Footer挂靠到RecyclerView
*
* @param recyclerView
*/
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
if (manager instanceof GridLayoutManager) { // 布局是GridLayoutManager所管理
final GridLayoutManager gridLayoutManager = (GridLayoutManager) manager;
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
// 如果是Header、Footer的对象则占据spanCount的位置,否则就只占用1个位置
return (isHeader(position) || isFooter(position)) ? gridLayoutManager
.getSpanCount() : 1;
}
});
}
}
/**
* 判断是否是Header的位置
* 如果是Header的则返回true否则返回false
*
* @param position
* @return
*/
public boolean isHeader(int position) {
return position >= 0 && position < mHeaderViews.size();
}
/**
* 判断是否是Footer的位置
* 如果是Footer的位置则返回true否则返回false
*
* @param position
* @return
*/
public boolean isFooter(int position) {
return position < getItemCount() && position >= getItemCount() - mFooterViews.size();
}
@Override
public int getItemCount() {
if (mAdapter != null) {
return getHeadersCount() + getFootersCount() + mAdapter.getItemCount();
} else {
return getHeadersCount() + getFootersCount();
}
}
@Override
public int getItemViewType(int position) {
if (mCurrentPosition == -1) {
mCurrentPosition = position; // 这是第一个HeaderView
}
int numHeaders = getHeadersCount();
if (position < numHeaders) {
if (position != mCurrentPosition) { // 这是第二个HeaderView
return RecyclerView.INVALID_TYPE - 1; // 这是第二个HeaderView所占用的空间
}
return RecyclerView.INVALID_TYPE; // 这是第一个HeaderView所占用的空间
}
int adjPosition = position - numHeaders;
int adapterCount = 0;
if (mAdapter != null) {
adapterCount = mAdapter.getItemCount();
if (adjPosition < adapterCount) {
return mAdapter.getItemViewType(adjPosition);
}
}
return RecyclerView.INVALID_TYPE - 2; // 说明是Footer的所占用的空间
}
@Override
public long getItemId(int position) {
int numHeaders = getHeadersCount();
if (mAdapter != null && position >= numHeaders) {
int adjPosition = position - numHeaders;
int adapterCount = mAdapter.getItemCount();
if (adjPosition < adapterCount) {
return mAdapter.getItemId(adjPosition); // 不是Header和Footer则返回其itemId
}
}
return -1;
}
@Override
public RecyclerView.Adapter getWrapperAdapter() {
return mAdapter;
}
private static class HeaderViewHolder extends RecyclerView.ViewHolder {
public HeaderViewHolder(View itemView) {
super(itemView);
}
}
}