美文网首页
自定义Recyclerview实现上拉加载

自定义Recyclerview实现上拉加载

作者: Sunyard_QiL | 来源:发表于2018-05-22 19:17 被阅读0次

    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

    相关文章

      网友评论

          本文标题:自定义Recyclerview实现上拉加载

          本文链接:https://www.haomeiwen.com/subject/kwekjftx.html