RecyclerView实现上拉分页加载以及下拉刷新

来源:互联网 发布:linux重启tomcat错误 编辑:程序博客网 时间:2024/04/27 18:06

最近公司里提出一个需求,实现recyclerview的分页加载。之前在学校一直想实现这个功能一直没有合适的时间去研究,现在抽空实现了一个简单的Demo。

实现的功能:

  • 第一次进入界面显示SwipeRefreshLayout的下拉刷新效果
  • 上拉分页加载,底部显示正在加载
  • 数据全部加载完毕后显示没有更多

效果如下

demo

源码GIT地址,欢迎Star、Fork。

代码实现:

首先贴上RecyclerView的adapter的关键代码,在代码中有详细的注释

两个不同的ViewHolder,分别用来初始化正常的item以及脚布局。

    /**     * 正常布局的ViewHolder     */ class MyViewHolder extends RecyclerView.ViewHolder {        public MyViewHolder(View itemView) {            super(itemView);        }    }    /**     * 脚布局的ViewHolder     */    public static class FootViewHolder extends RecyclerView.ViewHolder {        public FootViewHolder(View itemView) {            super(itemView);        }      }

这里通过重写getItemViewType 方法来获取不同类型的布局。重写getItemCount,由于多加了一个脚布局所以要+1;

   public int getItemViewType(int position) {        //如果position加1正好等于所有item的总和,说明是最后一个item,将它设置为脚布局        if (position + 1 == getItemCount()) {            return TYPE_FOOTER;        } else {            return TYPE_ITEM;        }    }    @Override    public int getItemCount() {        return mList.size() == 0 ? 0 : mList.size() + 1;    }     

onCreateViewHolder判断类型,以及加载不同的布局。同时在onBindViewHolder中进行不同情形下的处理

 @Override    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        if (viewType == TYPE_ITEM) {            View view = View.inflate(mContext, R.layout.list_item, null);            MyViewHolder holder = new MyViewHolder(view);            return holder;        } else if (viewType == TYPE_FOOTER) {            //脚布局            View view = View.inflate(mContext, R.layout.foot_item, null);            FootViewHolder footViewHolder = new FootViewHolder(view);            return footViewHolder;        }        return null;    }    @Override    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {        if (holder instanceof MyViewHolder) {            ((MyViewHolder) holder).mTextView.setText(mList.get(position));        } else if (holder instanceof FootViewHolder) {            FootViewHolder footViewHolder = (FootViewHolder) holder;            if (position == 0) {//如果第一个就是脚布局,,那就让他隐藏                            footViewHolder.mProgressBar.setVisibility(View.GONE);                footViewHolder.tv_line1.setVisibility(View.GONE);                footViewHolder.tv_line2.setVisibility(View.GONE);                footViewHolder.tv_state.setText("");            }            switch (footer_state) {//根据状态来让脚布局发生改变//              case PULL_LOAD_MORE://上拉加载//                   footViewHolder.mProgressBar.                                           setVisibility(View.GONE);//                    footViewHolder.tv_state.setText("上拉加载更多");//                    break;                case LOADING_MORE:                    footViewHolder.mProgressBar.                    setVisibility(View.VISIBLE);                    footViewHolder.tv_line1.setVisibility(View.GONE);                    footViewHolder.tv_line2.setVisibility(View.GONE);                    footViewHolder.tv_state.setText("正在加载...");                    break;                case NO_MORE:                    footViewHolder.mProgressBar.setVisibility(View.GONE);                    footViewHolder.tv_line1.setVisibility(View.VISIBLE);                    footViewHolder.tv_line2.setVisibility(View.VISIBLE);                    footViewHolder.tv_state.setText("我是有底线的");                    footViewHolder.tv_state.                    setTextColor(Color.parseColor("#ff00ff"));                    break;            }        }    }
    /**     * 改变脚布局的状态的方法,在activity根据请求数据的状态来改变这个状态     *     * @param state     */    public void changeState(int state) {        this.footer_state = state;        notifyDataSetChanged();    }

接的是在activity中实现我们所需要的效果

下拉刷新的实现,通过SwipeRefreshLayout,这里大家应该都比较熟悉

        //设置下拉刷新的颜色        mSwipeRefreshLayout.setColorSchemeResources(R.color.colorAccent);        //第一次加载刷新        mSwipeRefreshLayout.post(new Runnable() {            @Override            public void run() {                mSwipeRefreshLayout.setRefreshing(true);            }        });        //设置下拉刷新        mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {            @Override            public void onRefresh() {                mList.clear();                initData();                //改变foot_item的状态,这里可以根据自身的业务需求相应修改                mAdapter.changeState(1);                page = 0;            }        });

接着是分页上拉加载的实现,也是主要部分,在分页加载这里的逻辑可以根据业务的需要自己改变,我是通过页数来判断,具体的可以看源码。

//给recyclerView添加滑动监听        mRecycler.addOnScrollListener(new RecyclerView.OnScrollListener() {            @Override            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {                super.onScrollStateChanged(recyclerView, newState);                //判断是否在执行下拉刷新                boolean isRefreshing = mSwipeRefreshLayout.isRefreshing();                Log.d(TAG, "onScrollStateChanged: "+isRefreshing);                /*                到达底部了,如果不加!isLoading的话到达底部如果还一滑动的话就会一直进入这个方法,就一直去做请求网络的操作,这样的用户体验肯定不好.添加一个判断,每次滑倒底只进行一次网络请求去请求数据。当请求完成后,在把isLoading赋值为false,下次滑倒底又能进入这个方法了    */                if (newState == RecyclerView.SCROLL_STATE_IDLE && lastVisibleItem + 1 == mAdapter.getItemCount()  && !isLoading && !isRefreshing) {                    //到达底部之后如果footView的状态不是正在加载的状态,就将 他切换成正在加载的状态                    if (page < totlePage) {                        Log.e("duanlian", "onScrollStateChanged: " + "进来了");                        isLoading = true;                        //改变状态,说明数据未全部加载完                        mAdapter.changeState(1);                        //延迟2秒,模拟网络请求过程                        handler.postDelayed(new Runnable() {                            @Override                            public void run() {                                getData();                                page++;                            }                        }, 2000);                    } else {                      //改变状态,说明数据已经全部加载完                        mAdapter.changeState(2);                    }                }            }            @Override            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {                super.onScrolled(recyclerView, dx, dy);                //拿到最后一个出现的item的位置                lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();            }

这里通过监听RecyclerView的滚动事件RecyclerView.OnScrollListener()实现的,它提供了两个方法:

        /**         * 当RecyclerView的滑动状态改变时触发         */        public void onScrollStateChanged(RecyclerView recyclerView, int newState){}        /**         * 当RecyclerView滑动时触发         * 类似点击事件的MotionEvent.ACTION_MOVE         */        public void onScrolled(RecyclerView recyclerView, int dx, int dy){}

RecyclerView的滑动状态有如下三种:

    /**     * The RecyclerView is not currently scrolling.     * 手指离开屏幕     */    public static final int SCROLL_STATE_IDLE = 0;    /**     * The RecyclerView is currently being dragged by outside input such as user touch input.     * 手指触摸屏幕     */    public static final int SCROLL_STATE_DRAGGING = 1;    /**     * The RecyclerView is currently animating to a final position while not under     * outside control.     * 手指加速滑动并放开,此时滑动状态伴随SCROLL_STATE_IDLE     */    public static final int SCROLL_STATE_SETTLING = 2;

好了,结合代码里的注释相信你能看懂,欢迎大家批评指正QAQ。

参考资料:http://blog.csdn.net/leoleohan/article/details/50989549/

0 0
原创粉丝点击