如何给RecyclerView(GridLayoutManager)添加多个Header和Footer

基于前面的博文给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);
        }
    }
}

猜你喜欢

转载自1124117571.iteye.com/blog/2332373
今日推荐