RecycleView終極封裝(添加頭、尾佈局)

今天給你們帶來一個對於Recycleview的終極封裝包含頭、尾。

GitHub傳送門:歡迎Start android

https://github.com/yang0range/BaseRecycleView複製代碼


若是以爲文章還有用的話,歡迎來一波點贊,轉發,收藏三連擊!

背景

Recycleview能夠說是咱們最經常使用的控件之一,只要有列表幾乎就會用到。可是有沒有由於每次要重寫一大堆同樣的相同代碼而感到煩惱和厭倦,咱們就想到能不能把相同內容進行封裝,答案固然是能夠,根據咱們目前項目裏的需求,又加上了頭、尾佈局。

效果

首先咱們經過幾個GIF來展現一下咱們實現的效果

尾佈局爲AUTO_LOAD.gif


尾佈局爲LOAD_END.gif


尾佈局爲LOAD_ERROR.gif


以上三種狀態咱們都會經過後面的代碼來詳細說明。git

代碼實現

頭佈局

頭佈局沒什麼可說的,在ListView當中能夠直接經過addHeaderView()進行添加頭佈局,可是對於Recyclerview當中,並無這種直接添加頭佈局的方法,那麼咱們就須要經過Adapter當中來實現。github

尾佈局

尾佈局,咱們設定有三種不一樣的模式,這個在咱們下拉加當中可能遇到的狀況
1.自動加載 AUTO_LOAD
2.加載到底 LOAD_END
3.加載失敗 LOAD_ERROR
根據不一樣的佈局咱們設置了不一樣的提示語
<string name="list_index_auto_loading">(>﹏<) 賣力加載中~</string>
<string name="list_index_loading_end">(>﹏<) 暫時就這麼多了~</string>
<string name="list_index_loading_error">(>﹏<) 點我加載更多~</string>bash

點擊事件

由於Recycleview自己並無點擊事件,天然咱們須要添加上點擊事件,同時咱們對頭佈局,尾佈局都增長點擊事件
完整的BaseRecycleViewAdapter代碼以下:app

public abstract class BaseRecycleViewAdapter<T> extends RecyclerView.Adapter {

    public static final int TYPE_NORMAL = 0;

    public static final int TYPE_HEADER = 1;

    public static final int TYPE_FOOTER = 2;

    public static final int TYPE_AUTO_MORE = 3;

    private AutoMoreListener mMoreListener;

    protected List<T> mList;

    protected Context mContext;

    protected OnItemClickListener<T> mOnItemClickListener;

    protected OnItemLongClickListener mOnItemLongClickListener;

    protected OnHeaderItemClickListener mOnHeaderItemClickListener;

    private MORE_TYPE mMoreType = MORE_TYPE.AUTO_LOAD;

    public enum MORE_TYPE {
        AUTO_LOAD, LOAD_END, LOAD_ERROR
    }

    protected BaseRecycleViewAdapter(Context context, List<T> list) {
        mContext = context;
        mList = list;
    }

    protected int getRealPosition(int position) {
        if (getViewHeaderResource() > 0) {
            return position - 1;
        } else {
            return position;
        }
    }

    @Override
    public int getItemViewType(int position) {
        if (getMoreLoadLayoutResId() > 0 && position == getItemCount() - 1) {
            return TYPE_AUTO_MORE;
        }
        if (position == 0) {
            if (mList == null || mList.isEmpty()) {
                if (getViewHeaderResource() > 0) {
                    return TYPE_HEADER;
                } else if (getFooterViewResource() > 0) {
                    return TYPE_FOOTER;
                } else {
                    return TYPE_NORMAL;
                }
            } else {
                if (getViewHeaderResource() > 0) {
                    return TYPE_HEADER;
                } else {
                    return TYPE_NORMAL;
                }
            }
        } else if (position == getItemCount() - 1) {
            if (getFooterViewResource() > 0) {
                return TYPE_FOOTER;
            } else {
                return TYPE_NORMAL;
            }
        } else {

            return TYPE_NORMAL;
        }
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == TYPE_HEADER) {
            return getRecycleViewHeaderHolder(LayoutInflater.from(mContext).inflate(getViewHeaderResource(), parent, false));
        } else if (viewType == TYPE_FOOTER) {
            return getRecycleViewFooterHolder(LayoutInflater.from(mContext).inflate(getFooterViewResource(), parent, false));
        } else if (viewType == TYPE_AUTO_MORE) {
            return new MoreLoadViewHolder(LayoutInflater.from(mContext).inflate(getMoreLoadLayoutResId(), parent, false));
        } else {
            return getRecycleViewHolder(LayoutInflater.from(mContext).inflate(getViewResource(), parent, false));
        }
    }

    @Override
    public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
        final int viewType = getItemViewType(position);
        if (viewType == TYPE_AUTO_MORE) {
            bindMoreViewHolder((MoreLoadViewHolder) holder);
            return;
        }
        if (viewType == TYPE_HEADER) {
            dataReadByHeader(holder, position);
            if (mOnHeaderItemClickListener != null) {
                holder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        mOnHeaderItemClickListener.onHeaderClick(holder.itemView, position, mList.get(position));
                    }
                });
            }
        } else if (viewType == TYPE_FOOTER) {
            dataReadByFooter(holder, position);
        } else {
            final int pos = getRealPosition(position);
            dataRead(holder, pos);
            if (mOnItemClickListener != null) {
                holder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (viewType != TYPE_NORMAL) {
                            return;
                        }
                        mOnItemClickListener.onItemClick(holder.itemView, position, mList.get(pos));
                    }
                });
            }
            if (mOnItemLongClickListener != null) {
                holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                    @Override
                    public boolean onLongClick(View v) {
                        if (viewType != TYPE_NORMAL) {
                            return false;
                        } else {
                            mOnItemLongClickListener.onItemLongClick(holder.itemView, position, mList.get(pos));
                            return true;
                        }
                    }
                });
            }
        }
    }

    @Override
    public int getItemCount() {
        int count = mList == null ? 0 : mList.size();
        if (count == 0) {
            return count;
        }
        if (getViewHeaderResource() > 0) {
            count += 1;
        }
        if (getFooterViewResource() > 0) {
            count += 1;
        }
        if (getMoreLoadLayoutResId() > 0) {
            count += 1;
        }
        return count;
    }

    protected static class MoreLoadViewHolder extends RecyclerView.ViewHolder {

        private TextView mTvMsg;

        public MoreLoadViewHolder(View itemView) {
            super(itemView);
            mTvMsg = (TextView) itemView.findViewById(R.id.tv_more_loading);
        }
    }

    protected int getMoreLoadLayoutResId() {

        return R.layout.item_new_more_footer_layout;
    }

    private void bindMoreViewHolder(MoreLoadViewHolder holder) {
        if (mMoreType == MORE_TYPE.AUTO_LOAD) {
            holder.mTvMsg.setText(mContext.getString(R.string.list_index_auto_loading));
        } else if (mMoreType == MORE_TYPE.LOAD_END) {
            holder.mTvMsg.setText(getFooterTip());
        } else if (mMoreType == MORE_TYPE.LOAD_ERROR) {
            holder.mTvMsg.setText(mContext.getString(R.string.list_index_loading_error));
            holder.mTvMsg.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mMoreListener != null) {
                        setMoreType(MORE_TYPE.AUTO_LOAD);
                        notifyDataSetChanged();
                        mMoreListener.load();
                    }
                }
            });
        }
    }

    protected abstract int getViewResource();

    protected int getViewHeaderResource() {
        return 0;
    }

    protected int getFooterViewResource() {
        return 0;
    }

    protected RecyclerView.ViewHolder getRecycleViewHeaderHolder(View view) {
        throw new NullPointerException("getRecycleViewHeaderHolderv not init");
    }

    protected RecyclerView.ViewHolder getRecycleViewFooterHolder(View view) {
        throw new NullPointerException("getRecycleViewFooterHolder not init");
    }

    protected abstract RecyclerView.ViewHolder getRecycleViewHolder(View view);

    protected abstract void dataRead(RecyclerView.ViewHolder holder, int position);

    protected void dataReadByHeader(RecyclerView.ViewHolder holder, int position) {
        throw new NullPointerException("dataReadByHolder not init");
    }

    protected void dataReadByFooter(RecyclerView.ViewHolder holder, int position) {
        throw new NullPointerException("dataReadByFooter not init");
    }

    /**
     * 因爲不一樣列表底部顯示的東西可能不同 因此由子類傳入
     *
     * @return
     */
    protected String getFooterTip() {
        return mContext.getString(R.string.list_index_loading_end);
    }

    public interface OnItemClickListener<T> {

        void onItemClick(View view, int position, T entity);

    }

    public interface OnItemLongClickListener<T> {

        void onItemLongClick(View view, int position, T entity);
    }

    public interface OnHeaderItemClickListener<T> {

        void onHeaderClick(View view, int position, T entity);
    }

    public void setOnItemClickListener(OnItemClickListener<T> listener) {
        mOnItemClickListener = listener;
    }

    public void setOnHeaderItemClickListener(OnHeaderItemClickListener<T> listener) {
        mOnHeaderItemClickListener = listener;
    }

    public void setOnItemLongClickListener(OnItemLongClickListener<T> itemLongClickListener) {
        mOnItemLongClickListener = itemLongClickListener;
    }

    public void setMoreType(MORE_TYPE moreType) {
        mMoreType = moreType;
    }

    public MORE_TYPE getMoreType() {
        return mMoreType;
    }

    public void setMoreListener(AutoMoreListener listener) {
        mMoreListener = listener;
    }

    public interface AutoMoreListener {

        void load();
    }

}

複製代碼

有了這個BaseRecycleViewAdapter那麼咱們再寫Adapter的時候,直接繼承這個BaseRecycleViewAdapter就能夠了
我是用Kotlin寫的,習慣用Java的小夥伴自行轉成Javaide

package demo.rlv.cehome.com.alldemo.view

import android.content.Context
import android.support.v7.widget.RecyclerView
import android.view.View
import android.widget.TextView
import demo.rlv.cehome.com.myapplication.R
import demo.rlv.view.BaseRecycleViewAdapter


/**
 * @author yangzc
 * @data 2019/3/14 10:56
 * @desc
 */
open class RlvAdapter(context: Context, list: List<String>) : BaseRecycleViewAdapter<String>(context, list as MutableList<String>?) {

    override fun getViewResource(): Int {
        return R.layout.item_normal
    }


    override fun getViewHeaderResource(): Int {
        return return R.layout.item_head
    }

    override fun getRecycleViewHolder(view: View): RecyclerView.ViewHolder {
        return RlvViewHolder(view)
    }

    override fun dataRead(holder: RecyclerView.ViewHolder, position: Int) {
        val h = holder as RlvViewHolder
        h.tv.text = mList[position]
    }

    override fun getRecycleViewHeaderHolder(view: View): RecyclerView.ViewHolder {
        return RlvHeadViewHolder(view)
    }

    override fun dataReadByHeader(holder: RecyclerView.ViewHolder?, position: Int) {
        val h = holder as RlvHeadViewHolder
        h.tv_head.text = "這個是頭部"
    }


    private inner class RlvViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        internal val tv: TextView = itemView.findViewById(R.id.tv)
    }

    private inner class RlvHeadViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        internal val tv_head: TextView = itemView.findViewById(R.id.tv_head)
    }


}

複製代碼

項目地址

github.com/yang0range/…佈局

歡迎關注公共號

關注公共號便可得到最新、最全Android知識。
相關文章
相關標籤/搜索