自定义Recyclerview实现上拉加载

android提供了下拉刷新控件SwipeRefreshLayout,并没有提供上拉加载控件,Recyclerview又并不像Listview一样提供addHead,addFoot接口,只能通过自定义实现。本文实现了Item相同时recyclerview的上拉加载功能。

1526974666967[1].gif

首先定义一个基类adapter,代码里注释写的很清楚了

public abstract class BaseRecycleAdapter<T> extends RecyclerView.Adapter<BaseRecycleAdapter.BaseHolder> {

    public List<T> mDatas;

    private final Context mContext;

    private static final int TYPE_ITEM = 0;       //普通Item View
    private static final int TYPE_FOOTER = 1;    //底部FootView

    public static final int PULL_UP_LOAD_MORE = 0;  //上拉加载
    public static final int LOADING_MORE = 1;      //正在加载中
    public static final int NO_MORE_DATA = 2;     //加载完成没有数据

    private int load_more_status = 0;               //上拉加载状态默认0
    private OnItemClickListener onItemClickListener;

    public BaseRecycleAdapter(Context context) {
        mContext = context;
    }

    /**
     * 设置数据源 泛型T代表list的泛型
     * @param datas
     */
    public void setData(List<T> datas) {
        mDatas = datas;
    }

    /**
     * item点击事件
     * @param onItemClickListener
     */
    public void setOnItemClickListener(OnItemClickListener  onItemClickListener){
        this.onItemClickListener = onItemClickListener;
    }

    /**
     * 根据不同的viewType创建不同的holder
     * @param parent
     * @param viewType
     * @return
     */
    @Override
    public BaseHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        BaseHolder holder = null;
        View view = null;
        if (viewType == TYPE_ITEM) {
            view = LayoutInflater.from(mContext).inflate(getLayoutId(viewType), parent, false);
        } else {
            view = LayoutInflater.from(mContext).inflate(R.layout.pull_load_more, parent, false);
        }
        holder = new BaseHolder(view);
        return holder;
    }


    @Override
    public void onBindViewHolder(BaseHolder holder, final int position) {

        //底部Item 根据传入的状态更改布局(load_more_status)

        if (holder.getItemViewType() == BaseRecycleAdapter.TYPE_FOOTER) {
            ProgressBar progressBar = (ProgressBar) holder.getView(R.id.progressBar);
            TextView tv_progress_text = (TextView) holder.getView(R.id.tv_progress_text);
            switch (load_more_status){
                case LOADING_MORE:
                    tv_progress_text.setText("正在加载数据");
                    progressBar.setVisibility(View.VISIBLE);
                    break;
                case PULL_UP_LOAD_MORE:
                    if (getItemCount()<10){
                        progressBar.setVisibility(View.INVISIBLE);
                        tv_progress_text.setText("");
                    }else {
                        tv_progress_text.setText("上拉加载更多");
                        progressBar.setVisibility(View.INVISIBLE);
                    }
                    break;
                case NO_MORE_DATA:
                    tv_progress_text.setText("没有更多数据了");
                    progressBar.setVisibility(View.INVISIBLE);
                    break;
            }
        }

        //普通Item 绑定数据
        if (holder.getItemViewType() == BaseRecycleAdapter.TYPE_ITEM) {
            onBindData(holder, position, mDatas);
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (onItemClickListener!=null){
                        onItemClickListener.onItemClick(position,v);
                    }
                }
            });
        }
    }

    /**
     * 获取item数量
     * @return
     */
    @Override
    public int getItemCount() {
            return mDatas == null ? 0 : mDatas.size() + 1;
    }

    /**
     * 获取item类型(普通item 、底部item)
     * @param position
     * @return
     */
    @Override
    public int getItemViewType(int position) {
        if (mDatas == null)
            return TYPE_ITEM;
        if (position + 1 == getItemCount()) {
            return TYPE_FOOTER;
        } else {
            return TYPE_ITEM;
        }
    }

    /**
     * 根据传入status改变foot状态并刷新数据
     * @param status
     */
    public void changeMoreStatus(int status) {
        load_more_status = status;
        notifyDataSetChanged();
    }

    /**
     * 根据type 返回不同的布局
     *
     * @param type
     * @return
     */
    public abstract int getLayoutId(int type);

    /**
     * 绑定数据(做成抽象 在子类实现)
     * @param holder
     * @param position
     * @param mDataList
     */
    public abstract void onBindData(BaseHolder holder, int position, List<T> mDataList);

    public static class BaseHolder extends RecyclerView.ViewHolder {
        private Map<Integer, View> mViewMap;
        public View mView;

        public BaseHolder(View itemView) {
            super(itemView);
            mView = itemView;
            mViewMap = new HashMap<>();
        }

        public View getView(int id) {
            View view = mViewMap.get(id);
            if (view == null) {
                view = mView.findViewById(id);
                mViewMap.put(id, view);
            }
            return view;
        }
    }


}

自定义Recyclerview

package com.wckj.myrecyclerview;

import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;

import com.wckj.myrecyclerview.Test.BaseRecycleAdapter;

/**
 * Created by HQL
 * on 2018/5/21 0021.
 */

public class MyRecyclerView extends RecyclerView {

    private BaseRecycleAdapter myLoadMoreAdapter;
    OnloadListener mOnLoadListener = null;
    private boolean haveData = true;

    public MyRecyclerView(Context context) {
        this(context,null);
    }

    public MyRecyclerView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public MyRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setOnScrollListener(null);
    }

    @Override
    public void setOnScrollListener(OnScrollListener listener) {
        LoadMoreDataListener loadMoreListener = new LoadMoreDataListener(listener);
        super.setOnScrollListener(loadMoreListener);
    }

    @Override
    public void setAdapter(Adapter adapter) {
        if (!( adapter instanceof BaseRecycleAdapter)){
            return;
        }
        myLoadMoreAdapter = (BaseRecycleAdapter) adapter;
        super.setAdapter(myLoadMoreAdapter);

    }
    //自定义的接口方便回调
    public void setOnLoadListener(OnloadListener listener) {
        mOnLoadListener = listener;
    }

    //重写OnScrollListener
    class LoadMoreDataListener extends OnScrollListener{
        private OnScrollListener listener;
        private int lastVisibleItem;


        public LoadMoreDataListener(OnScrollListener listener) {
            this.listener = listener;
        }

        /**
         * 当目前显示是最后一个条目的时候
         * @param recyclerView
         * @param newState
         */
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            //当目前显示是最后一个条目的时候继续向下执行
            if (newState == RecyclerView.SCROLL_STATE_IDLE &&lastVisibleItem + 1 == getAdapter().getItemCount()){
                if (mOnLoadListener != null && haveData) {
                    //改变底部foot状态
                    myLoadMoreAdapter.changeMoreStatus(BaseRecycleAdapter.LOADING_MORE);
                    //通过接口回调回去
                    mOnLoadListener.OnLoadData();
                }
            }
            if (listener != null) {
                listener.onScrollStateChanged(recyclerView, newState);
            }
        }

        /**
         * 计算最后一个可见条目(lastVisibleItem)
         * 目前只支持 LinearLayoutManager和GridLayoutManager两种类型
         * @param recyclerView
         * @param dx
         * @param dy
         */
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            if (getLayoutManager() instanceof LinearLayoutManager) {
                LinearLayoutManager lm = (LinearLayoutManager) getLayoutManager();
                lastVisibleItem = lm.findLastVisibleItemPosition();
            } else if (getLayoutManager() instanceof GridLayoutManager) {
                GridLayoutManager gm = (GridLayoutManager) getLayoutManager();
                 lastVisibleItem = gm.findLastVisibleItemPosition();
            }
            if (listener != null) {
                listener.onScrolled(recyclerView, dx, dy);
            }

        }

    }

    /**
     * 数据加载完成后调用
     * @param haveData
     */
    public void loadComplete(final boolean haveData) {
        //判断时候还有数据
        this.haveData = haveData;

        //改变底部foot状态
        if (!haveData) {
            myLoadMoreAdapter.changeMoreStatus(BaseRecycleAdapter.NO_MORE_DATA);
        } else {
            myLoadMoreAdapter.changeMoreStatus(BaseRecycleAdapter.PULL_UP_LOAD_MORE);
        }

    }

}


在布局文件使用

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.wckj.myrecyclerview.MainActivity">

    <com.wckj.myrecyclerview.MyRecyclerView
        android:id="@+id/my_recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </com.wckj.myrecyclerview.MyRecyclerView>

</LinearLayout>

需要用到的接口

 interface OnloadListener {

    void OnLoadData();
}

通过自定义的adapter继承上面的BaseRecycleAdapter

package com.wckj.myrecyclerview.Test;

import android.content.Context;
import android.widget.TextView;

import com.wckj.myrecyclerview.R;

import java.util.List;

/**
 * Created by HQL
 * on 2018/5/22 0022.
 */

public class MyRecyViewAdapter extends BaseRecycleAdapter<String> {
    public MyRecyViewAdapter(Context context) {
        super(context);
    }

    @Override
    public int getLayoutId(int type) {
        return R.layout.normal_item;
    }

    @Override
    public void onBindData(BaseHolder holder, int position, List<String> data) {

        TextView view = (TextView) holder.getView(R.id.tv_normal_item);
        view.setText(data.get(position));
    }

}

在Activity中使用

package com.wckj.myrecyclerview;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.view.View;

import com.wckj.myrecyclerview.Test.MyRecyViewAdapter;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity implements OnItemClickListener {


    private MyRecyclerView myRecyclerView;
    private ArrayList<String> data = new ArrayList<>();
    private int j = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initData();
        myRecyclerView = (MyRecyclerView) findViewById(R.id.my_recyclerview);
        myRecyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false));
        MyRecyViewAdapter adapter = new MyRecyViewAdapter(this);
        adapter.setData(data);
        adapter.setOnItemClickListener(this);
        myRecyclerView.setAdapter(adapter);
        myRecyclerView.setOnLoadListener(new OnloadListener() {
            @Override
            public void OnLoadData() {
                if (j==5) {
                    //数据加载完成调用loadComplete,改变foot状态
                    myRecyclerView.loadComplete(false);
                    return;
                }
                initData();
            }
        });
    }

    private void initData() {
        j++;

        for (int i=0;i<20;i++){
            data.add("我是一个粉刷匠,代号"+i);
        }
    }

    @Override
    public void onItemClick(int position, View view) {
        
    }
}

基本上就是这些,稍后代码会上传github有需要可以自行下载

代码地址:https://github.com/aaahql2016/LoadMoreRecyclerview

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。