RecyclerView(二)——为recyclerView增加header和footer

  关于这个问题,我建议大家看看鸿大神的一篇博客,连接为http://blog.csdn.net/lmj623565791/article/details/51854533


  首先说一点,在实际项目中有时会遇到本来我们的列表是不带Header的,突然一下产品抛出个需求要增加Header,我们又不得不去实现。
  纵观整个界面,我们会发现,不管是Header还是Footer,都只不过是整个另一种viewType的item罢了。按照一般的做法,我们会想到增加一个特殊的viewType,然后去修改Adapter中的代码。那么,问题来了,你能保证这个Adapter是否只会在这一个地方使用,修改过后不会影响其他使用过这个Adapter的位置不出问题?谁也不能保证这点。按照我的原则来说,没有十足的把握或者还不到非做不可的情况下,那么就绝不要去修改前辈已经写好的代码。于是,我们可以考虑使用装饰着模式去装饰我们原来的Adapter,然后在需要的地方使用我们新的Adapter即可。

  先分析一下需求,无非就是以下几个功能:
  - 可增加HeaderView
  - 可增加FooterView
  - 适配多种LayoutManager

我们希望有几个方法:
void addHeaderView(View view);
void addHeaderView(View view, OnClickListener listener);
void addFooterView(View view);
void addFooterView(View view, OnClickListener listener);

直接看增加的代码:
RecyclerViewHeaderFooterWrapper

package com.zou.zohar.recyclerviewdemo.ui.adapter;

import android.support.v4.util.SparseArrayCompat;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;

/**
 * desc:
 * Created by Zohar on 2017/4/27.
 */
public class RecyclerViewHeaderFooterWrapper extends RecyclerView.Adapter {
    //BASE_ITEM_TYPE_HEADER 和 BASE_ITEM_TYPE_FOOTER 没有什么特殊的含义,
    //只是用作将HeaderView和FooterView存放在SparseArrayCompat<View>容器中时的key值,方便取用
    //具体使用见 addHeaderView(View view) 和 getItemViewType(int position) 以及 onCreateViewHolder(ViewGroup parent, int viewType) 方法
    private static final int BASE_ITEM_TYPE_HEADER = 100000;
    private static final int BASE_ITEM_TYPE_FOOTER = 200000;

    private SparseArrayCompat<View> mHeaderViews = new SparseArrayCompat<>();//HeaderView的集合
    private SparseArrayCompat<View.OnClickListener> mHeaderViewClickListeners = new SparseArrayCompat<>();//HeaderView监听事件的集合

    private SparseArrayCompat<View> mFootViews = new SparseArrayCompat<>();//FooterView的集合
    private SparseArrayCompat<View.OnClickListener> mFootViewClickListeners = new SparseArrayCompat<>();//FooterView监听事件的集合

    private RecyclerView.Adapter mAdapter;//控制内容item的Adapter

    public RecyclerViewHeaderFooterWrapper(RecyclerView.Adapter adapter) {
        mAdapter = adapter;
    }

    /**
     * Returns true if the item is HeaderView
     *
     * @param position position of the item to be examined
     * @return true if item is HeaderView
     */
    private boolean isHeaderView(int position) {
        return position < getHeadersCount();
    }

    /**
     * Returns true if the item is FooterView
     *
     * @param position position of the item to be examined
     * @return true if item is FooterView
     */
    private boolean isFooterView(int position) {
        return position >= getHeadersCount() + getRealItemCount();
    }

    /**
     * add a headerView
     *
     * @param view headerView
     */
    public void addHeaderView(View view) {
        addHeaderView(view, null);
    }

    /**
     * add a headerView with clickListener
     *
     * @param view     headerView
     * @param listener clickListener
     */
    public void addHeaderView(View view, View.OnClickListener listener) {
        if (listener != null) {
            mHeaderViewClickListeners.put(mHeaderViews.size() + BASE_ITEM_TYPE_HEADER, listener);
        }
        mHeaderViews.put(mHeaderViews.size() + BASE_ITEM_TYPE_HEADER, view);
    }

    /**
     * add a footerView
     *
     * @param view footerView
     */
    public void addFootView(View view) {
        addFootView(view, null);
    }

    /**
     * add a footerView with clickListener
     *
     * @param view     footerView
     * @param listener clickListener
     */
    public void addFootView(View view, View.OnClickListener listener) {
        if (listener != null) {
            mFootViewClickListeners.put(mFootViews.size() + BASE_ITEM_TYPE_FOOTER, listener);
        }
        mFootViews.put(mFootViews.size() + BASE_ITEM_TYPE_FOOTER, view);
    }

    /**
     * get the count of headers
     *
     * @return headersCount
     */
    public int getHeadersCount() {
        return mHeaderViews.size();
    }

    /**
     * get the count of footers
     *
     * @return footersCount
     */
    public int getFootersCount() {
        return mFootViews.size();
    }

    /**
     * get the count of items without headers and footers
     *
     * @return real itemsCount
     */
    private int getRealItemCount() {
        return mAdapter.getItemCount();
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (mHeaderViews.get(viewType) != null) {
            ViewHolder holder = new ViewHolder(mHeaderViews.get(viewType));
            if (mHeaderViewClickListeners.get(viewType) != null) {
                holder.itemView.setOnClickListener(mHeaderViewClickListeners.get(viewType));
            }
            return holder;
        } else if (mFootViews.get(viewType) != null) {
            RecyclerView.ViewHolder holder = new ViewHolder(mFootViews.get(viewType));
            if (mFootViewClickListeners.get(viewType) != null) {
                holder.itemView.setOnClickListener(mFootViewClickListeners.get(viewType));
            }
            return holder;
        }
        return mAdapter.onCreateViewHolder(parent, viewType);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (isHeaderView(position)) {
            return;
        }
        if (isFooterView(position)) {
            return;
        }
        mAdapter.onBindViewHolder(holder, position - getHeadersCount());
    }

    @Override
    public int getItemCount() {
        return getHeadersCount() + getFootersCount() + getRealItemCount();
    }

    @Override
    public int getItemViewType(int position) {
        if (isHeaderView(position)) {
            return mHeaderViews.keyAt(position);
        } else if (isFooterView(position)) {
            return mFootViews.keyAt(position - getHeadersCount() - getRealItemCount());
        }
        return mAdapter.getItemViewType(position - getHeadersCount());
    }

    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        mAdapter.onAttachedToRecyclerView(recyclerView);
        final RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            final GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
            final GridLayoutManager.SpanSizeLookup oldLookup = gridLayoutManager.getSpanSizeLookup();
            gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    int viewType = getItemViewType(position);
                    if (mHeaderViews.get(viewType) != null) {
                        return ((GridLayoutManager) layoutManager).getSpanCount();
                    } else if (mFootViews.get(viewType) != null) {
                        return ((GridLayoutManager) layoutManager).getSpanCount();
                    }
                    if (oldLookup != null) {
                        return oldLookup.getSpanSize(position);
                    }
                    return 1;
                }
            });
            gridLayoutManager.setSpanCount(gridLayoutManager.getSpanCount());
        }
    }

    private class ViewHolder extends RecyclerView.ViewHolder {

        ViewHolder(View itemView) {
            super(itemView);
        }
    }
}

使用起来也是相当的简单

        LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        recyclerView.setLayoutManager(layoutManager);

        RecyclerSimpleAdapter simpleAdapter = new RecyclerSimpleAdapter(dataList);//原本的Adapter
        recyclerViewHeaderFooterWrapper = new RecyclerViewHeaderFooterWrapper(simpleAdapter);
        //增加一个可点击的HeaderView
        TextView header1 = new TextView(this);
        header1.setText("header  1");
        recyclerViewHeaderFooterWrapper.addHeaderView(header1, new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Snackbar.make(v, "header  1", Snackbar.LENGTH_SHORT).show();
            }
        });
        //增加一个不可点击的HeaderView
        TextView header2 = new TextView(this);
        header2.setText("header  2");
        recyclerViewHeaderFooterWrapper.addHeaderView(header2);
        //增加一个可点击的FooterView
        TextView footer1 = new TextView(this);
        footer1.setText("footer  1");
        recyclerViewHeaderFooterWrapper.addFootView(footer1, new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Snackbar.make(v, "footer  1", Snackbar.LENGTH_SHORT).show();
            }
        });
        //增加一个不可点击的FooterView
        TextView footer2 = new TextView(this);
        footer2.setText("footer  2");
        recyclerViewHeaderFooterWrapper.addFootView(footer2);

        recyclerView.setAdapter(recyclerViewHeaderFooterWrapper);

RecyclerSimpleAdapter

package com.zou.zohar.recyclerviewdemo.ui.adapter;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.zou.zohar.recyclerviewdemo.R;

import java.util.List;

/**
 * desc:简单的RecyclerView适配器
 * Created by Zohar on 2017/4/7.
 */
public class RecyclerSimpleAdapter extends RecyclerView.Adapter<RecyclerSimpleAdapter.ViewHolder> {

    private List<String> dates = null;

    public RecyclerSimpleAdapter(List<String> dates) {
        this.dates = dates;
    }

    @Override
    public RecyclerSimpleAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list_layout, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final RecyclerSimpleAdapter.ViewHolder holder, final int position) {
        holder.textView.setText(dates.get(position));
    }

    @Override
    public int getItemCount() {
        return dates.size();
    }

    class ViewHolder extends RecyclerView.ViewHolder {
        LinearLayout llMain;
        TextView textView;

        ViewHolder(View itemView) {
            super(itemView);
            llMain = (LinearLayout) itemView.findViewById(R.id.ll_main);
            textView = (TextView) itemView.findViewById(R.id.text);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值