RecyclerView添加头尾部,支持网格和瀑布流布局

RecyclerView没有addHeaderView和addFooterView方法,参考了https://github.com/alicx/LoadMoreRecyclerView,在此基础上进行修改,感谢原作者,原来不支持网格和瀑布流添加头尾部,修改了支持网格,瀑布流布局添加多个头部和尾部view,以及全屏宽度item等

BaseRecycleView代码

import android.content.Context;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;

import java.util.ArrayList;
import java.util.List;

public class BaseRecycleView extends RecyclerView {

    /**
     * 布局类型
     */
    enum ITEM_TYPE {
        TYPE_NORMAL,//普通
        TYPE_GRID,//网格
        TYPE_STAGGERED//瀑布流
    }

    private ITEM_TYPE type = ITEM_TYPE.TYPE_NORMAL;//默认

    /**
     * item 类型
     */
    public final static int TYPE_NORMAL = 0;//普通item
    public final static int TYPE_GRID = 1;//网格item
    public final static int TYPE_STAGGERED = 2;//瀑布流item
    public final static int TYPE_HEADER = 3;//头部
    public final static int TYPE_FOOTER = 4;//尾部
    public final static int TYPE_SPECIAL = 5;//特殊item,在网格和瀑布流等布局需要全宽度item时调用

    private boolean mIsHeaderEnable = true;//是否显示头部
    private boolean mIsFooterEnable = true;//是否允许加载更多

    private int mHeaderCount = 0;//头部view数量
    private int mFooterCount = 0;//尾部view数量

    private List<View> mHeaderList = new ArrayList<>();//头部views
    private List<View> mFooterList = new ArrayList<>();//尾部views
    private List<Integer> mSpecialPositins = new ArrayList<>();//特殊view的positions

    private LinearLayout headerLayout;//尾部view
    private LinearLayout footerLayout;//头部view

    /**
     * 自定义实现了头部和底部的adapter
     */
    private AutoLoadAdapter mAutoLoadAdapter;
    private Adapter mItemAdapter;

    /**
     * 标记是否正在加载更多,防止再次调用加载更多接口
     */
    private boolean mIsLoadingMore;

    /**
     * 标记加载更多的position
     */
    private int mLoadMorePosition;

    /**
     * 加载更多的监听-业务需要实现加载数据
     */
    private LoadMoreListener mListener;

    public BaseRecycleView(Context context) {
        super(context);
        init();
    }

    public BaseRecycleView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public BaseRecycleView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    /**
     * 初始化-添加滚动监听
     * <p/>
     * 回调加载更多方法,前提是
     * <pre>
     *    1、有监听并且支持加载更多:null != mListener && mIsFooterEnable
     *    2、目前没有在加载,正在上拉(dy>0),当前最后一条可见的view是否是当前数据列表的最好一条--及加载更多
     * </pre>
     */
    private void init() {
        super.addOnScrollListener(new OnScrollListener() {

            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                if (null != mListener && mIsFooterEnable && !mIsLoadingMore && dy > 0) {
                    int lastVisiblePosition = getLastVisiblePosition();
                    if (lastVisiblePosition + 1 == mAutoLoadAdapter.getItemCount()) {
                        setLoadingMore(true);
                        mLoadMorePosition = lastVisiblePosition;
                        mListener.onLoadMore();
                    }
                }
            }
        });
    }

    /**
     * 设置布局类型
     */
    private void setItemType(ITEM_TYPE type) {
        this.type = type;
    }

    /**
     * 设置特殊item positions
     */
    public void setSpecialItem(List<Integer> specialItems) {
        this.mSpecialPositins = specialItems;
    }

    /**
     * 添加头部view
     */
    public void addHeaderView(View view) {
        mHeaderCount++;
        mHeaderList.add(view);
    }

    /**
     * 添加尾部view
     */
    public void addFooterView(View view) {
        mFooterCount++;
        mFooterList.add(view);
    }

    /**
     * 判断是否头部view
     */
    public boolean isHeaderPostion(int position) {
        if (position < mHeaderCount)
            return true;
        return false;
    }

    /**
     * 判断是否尾部view
     */
    public boolean isFooterPosition(int position) {
        if (position >= mHeaderCount + mItemAdapter.getItemCount())
            return true;
        return false;
    }

    /**
     * 判断是否特殊item
     */
    public boolean isSpecialItem(int position) {
        for (int p : mSpecialPositins) {
            if (p == position)
                return true;
        }
        return false;
    }

    /**
     * 获取header容器
     */
    private LinearLayout getHeaderLayout(ITEM_TYPE type) {
        if (headerLayout == null) {
            headerLayout = new LinearLayout(getContext());
            headerLayout.setLayoutParams(new StaggeredGridLayoutManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
            headerLayout.setOrientation(LinearLayout.VERTICAL);
        } else {
            //避免设置了网格布局后layoutparams变化
            if (type == ITEM_TYPE.TYPE_STAGGERED && !(headerLayout.getLayoutParams() instanceof StaggeredGridLayoutManager.LayoutParams))
                headerLayout.setLayoutParams(new StaggeredGridLayoutManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        }
        return headerLayout;
    }

    /**
     * 获取footer容器
     */
    private LinearLayout getFooterLayout(ITEM_TYPE type) {
        if (footerLayout == null) {
            footerLayout = new LinearLayout(getContext());
            footerLayout.setLayoutParams(new StaggeredGridLayoutManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
            footerLayout.setOrientation(LinearLayout.VERTICAL);
        } else {
            if (type == ITEM_TYPE.TYPE_STAGGERED && !(footerLayout.getLayoutParams() instanceof StaggeredGridLayoutManager.LayoutParams))
                footerLayout.setLayoutParams(new StaggeredGridLayoutManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        }
        return footerLayout;
    }

    /**
     * 设置加载更多的监听
     */
    public void setLoadMoreListener(LoadMoreListener listener) {
        mListener = listener;
    }

    @Override
    public void setLayoutManager(LayoutManager manager) {
        if (manager instanceof GridLayoutManager) {
            //头部,尾部,特殊item设置全宽度
            ((GridLayoutManager) manager).setSpanSizeLookup(new BaseSpanSizeLookup(((GridLayoutManager) manager).getSpanCount()));
            setItemType(ITEM_TYPE.TYPE_GRID);
        } else if (manager instanceof LinearLayoutManager) {
            setItemType(ITEM_TYPE.TYPE_NORMAL);
        } else if (manager instanceof StaggeredGridLayoutManager) {
            setItemType(ITEM_TYPE.TYPE_STAGGERED);
        }
        super.setLayoutManager(manager);
    }

    /**
     * 设置正在加载更多
     */
    public void setLoadingMore(boolean loadingMore) {
        this.mIsLoadingMore = loadingMore;
    }

    /**
     * 加载更多监听
     */
    public interface LoadMoreListener {
        void onLoadMore();
    }

    @Override
    public void setAdapter(Adapter adapter) {
        if (adapter != null) {
            mAutoLoadAdapter = new AutoLoadAdapter(adapter);
        }
        mItemAdapter = adapter;
        super.swapAdapter(mAutoLoadAdapter, true);
    }

    /**
     * 切换layoutManager
     */
    public void switchLayoutManager(LayoutManager layoutManager) {
        int firstVisiblePosition = getFirstVisiblePosition();
        setLayoutManager(layoutManager);
        //瀑布流不滚动到上一可见位置,避免滑动到头部后item重新排列
        if (!(layoutManager instanceof StaggeredGridLayoutManager))
            getLayoutManager().scrollToPosition(firstVisiblePosition);
    }

    /**
     * 获取第一条展示的位置
     */
    private int getFirstVisiblePosition() {
        int position;
        if (getLayoutManager() instanceof LinearLayoutManager) {
            position = ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
        } else if (getLayoutManager() instanceof GridLayoutManager) {
            position = ((GridLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
        } else if (getLayoutManager() instanceof StaggeredGridLayoutManager) {
            StaggeredGridLayoutManager layoutManager = (StaggeredGridLayoutManager) getLayoutManager();
            int[] lastPositions = layoutManager.findFirstVisibleItemPositions(new int[layoutManager.getSpanCount()]);
            position = getMinPositions(lastPositions);
        } else {
            position = 0;
        }
        return position;
    }

    /**
     * 获得当前展示最小的position
     */
    private int getMinPositions(int[] positions) {
        int size = positions.length;
        int minPosition = Integer.MAX_VALUE;
        for (int i = 0; i < size; i++) {
            minPosition = Math.min(minPosition, positions[i]);
        }
        return minPosition;
    }

    /**
     * 获取最后一条展示的位置
     */
    private int getLastVisiblePosition() {
        int position;
        if (getLayoutManager() instanceof LinearLayoutManager) {
            position = ((LinearLayoutManager) getLayoutManager()).findLastVisibleItemPosition();
        } else if (getLayoutManager() instanceof GridLayoutManager) {
            position = ((GridLayoutManager) getLayoutManager()).findLastVisibleItemPosition();
        } else if (getLayoutManager() instanceof StaggeredGridLayoutManager) {
            StaggeredGridLayoutManager layoutManager = (StaggeredGridLayoutManager) getLayoutManager();
            int[] lastPositions = layoutManager.findLastVisibleItemPositions(new int[layoutManager.getSpanCount()]);
            position = getMaxPosition(lastPositions);
        } else {
            position = getLayoutManager().getItemCount() - 1;
        }
        return position;
    }

    /**
     * 获得最大的位置
     */
    private int getMaxPosition(int[] positions) {
        int size = positions.length;
        int maxPosition = Integer.MIN_VALUE;
        for (int i = 0; i < size; i++) {
            maxPosition = Math.max(maxPosition, positions[i]);
        }
        return maxPosition;
    }

    /**
     * 设置头部view是否展示
     */
    public void setHeaderEnable(boolean enable) {
        mAutoLoadAdapter.setHeaderEnable(enable);
    }

    /**
     * 设置是否支持自动加载更多
     */
    public void setAutoLoadMoreEnable(boolean autoLoadMore) {
        mIsFooterEnable = autoLoadMore;
    }

    /**
     * 通知更多的数据已经加载
     */
    public void notifyMoreFinish(boolean hasMore) {
        setAutoLoadMoreEnable(hasMore);
        getAdapter().notifyItemRemoved(mLoadMorePosition);
        mIsLoadingMore = false;
    }

    /**
     * 网格布局头部,尾部,特殊item设置全宽度
     */
    private class BaseSpanSizeLookup extends GridLayoutManager.SpanSizeLookup {

        private int mSpanSize;

        public BaseSpanSizeLookup(int size) {
            mSpanSize = size;
        }

        @Override
        public int getSpanSize(int position) {
            return (isHeaderPostion(position) || isFooterPosition(position) || isSpecialItem(position - mHeaderCount)) ? mSpanSize : 1;
        }
    }

    /**
     * 基础adapter
     */
    public class AutoLoadAdapter extends Adapter<ViewHolder> {

        /**
         * 数据adapter
         */
        private Adapter mInternalAdapter;

        /**
         * 自定义头部,尾部holder
         */
        private HeaderViewHolder headerHolder;
        private FooterViewHolder footerHolder;

        public AutoLoadAdapter(Adapter adapter) {
            mInternalAdapter = adapter;
        }

        public void setHeaderEnable(boolean enable) {
            mIsHeaderEnable = enable;
        }

        /**
         * 需要计算上加载更多和添加的头部俩个
         */
        @Override
        public int getItemCount() {
            int count = mInternalAdapter.getItemCount();
            if (mIsFooterEnable) count += mHeaderCount;
            if (mIsHeaderEnable) count += mFooterCount;
            return count;
        }

        @Override
        public int getItemViewType(int position) {
            if (mHeaderCount > 0 && position < mHeaderCount && mIsHeaderEnable) {
                return TYPE_HEADER;
            }
            if (position >= mHeaderCount && position < mHeaderCount + mInternalAdapter.getItemCount() && mIsFooterEnable) {
                if (isSpecialItem(position - mHeaderCount))
                    return TYPE_SPECIAL;
                else {
                    if (type == ITEM_TYPE.TYPE_GRID)
                        return TYPE_GRID;
                    else if (type == ITEM_TYPE.TYPE_STAGGERED)
                        return TYPE_STAGGERED;
                    else
                        return TYPE_NORMAL;
                }
            } else {
                return TYPE_FOOTER;
            }
        }

        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            if (viewType == TYPE_HEADER)
                return new HeaderViewHolder(getHeaderLayout(type));
            else if (viewType == TYPE_FOOTER)
                return new FooterViewHolder(getFooterLayout(type));
            else
                return mInternalAdapter.onCreateViewHolder(parent, viewType);
        }

        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
            if (holder instanceof HeaderViewHolder) {
                headerHolder = (HeaderViewHolder) holder;
                if (type == ITEM_TYPE.TYPE_STAGGERED) {
                    if (!(headerHolder.contentLayout.getLayoutParams() instanceof StaggeredGridLayoutManager.LayoutParams))
                        headerHolder.contentLayout.setLayoutParams(new StaggeredGridLayoutManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
                    ((StaggeredGridLayoutManager.LayoutParams) headerHolder.itemView.getLayoutParams()).setFullSpan(true);
                }
                if (headerHolder.contentLayout.findViewWithTag(position) == null) {
                    if (mHeaderList.size() > 0 && position >= 0 && position < mHeaderList.size()) {
                        mHeaderList.get(position).setTag(position);
                        headerHolder.contentLayout.addView(mHeaderList.get(position));
                    }
                }
            } else if (holder instanceof FooterViewHolder) {
                footerHolder = (FooterViewHolder) holder;
                if (type == ITEM_TYPE.TYPE_STAGGERED) {
                    if (!(footerHolder.contentLayout.getLayoutParams() instanceof StaggeredGridLayoutManager.LayoutParams))
                        footerHolder.contentLayout.setLayoutParams(new StaggeredGridLayoutManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
                    ((StaggeredGridLayoutManager.LayoutParams) footerHolder.itemView.getLayoutParams()).setFullSpan(true);
                }
                int footPosition = position - mInternalAdapter.getItemCount() - mHeaderCount;
                if (footerHolder.contentLayout.findViewWithTag(footPosition) == null) {
                    if (mFooterList.size() > 0 && footPosition >= 0 && footPosition < mFooterList.size()) {
                        mFooterList.get(footPosition).setTag(footPosition);
                        footerHolder.contentLayout.addView(mFooterList.get(footPosition));
                    }
                }
            } else {
                if (type == ITEM_TYPE.TYPE_STAGGERED)
                    if (isSpecialItem(position - mHeaderCount)) {
                        if (!(holder.itemView.getLayoutParams() instanceof StaggeredGridLayoutManager.LayoutParams))
                            holder.itemView.setLayoutParams(new StaggeredGridLayoutManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, holder.itemView.getHeight()));
                        ((StaggeredGridLayoutManager.LayoutParams) holder.itemView.getLayoutParams()).setFullSpan(true);
                    }
                mInternalAdapter.onBindViewHolder(holder, position - mHeaderCount);
            }
        }

        public class FooterViewHolder extends ViewHolder {

            private LinearLayout contentLayout;

            public FooterViewHolder(View itemView) {
                super(itemView);
                contentLayout = (LinearLayout) itemView;
            }
        }

        public class HeaderViewHolder extends ViewHolder {

            private LinearLayout contentLayout;

            public HeaderViewHolder(View itemView) {
                super(itemView);
                contentLayout = (LinearLayout) itemView;
            }
        }

    }

    /**
     * item点击监听
     */
    public interface OnItemTouchListener {
        void onClickListener(int position);

        void onLongClickListener(int position);
    }

    /**
     * 基础viewholder,监听点击事件
     */
    public static class BaseViewHolder extends ViewHolder implements OnClickListener, OnLongClickListener {

        public int position;
        private OnItemTouchListener listener;

        public BaseViewHolder(View itemView, OnItemTouchListener listener) {
            super(itemView);
            this.listener = listener;
            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            if (listener != null)
                listener.onClickListener(position);
        }

        @Override
        public boolean onLongClick(View v) {
            if (listener != null)
                listener.onLongClickListener(position);
            return true;
        }
    }
}

demo地址:http://download.csdn.net/detail/ityangjun/9562209

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值