Android RecyclerView添加上拉加载更多效果

先看一下效果

刷新的时候是这样的:

没有更多的时候是这样的:

既然有刷新的时候有两种状态就要定义两个状态

//普通布局的type
static final int TYPE_ITEM = 0;
//脚布局
static final int TYPE_FOOTER = 1;

在特定的时候去显示:

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

然后根据这个type来inflate不同的布局:

 @Override
  public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == TYPE_ITEM) {
      View view = View.inflate(mContext, R.layout.item_recycler, null);
      MyViewHolder holder = new MyViewHolder(view);
      return holder;
    } else if (viewType == TYPE_FOOTER) {
      //脚布局
      View view = View.inflate(mContext, R.layout.recycler_load_more_layout, null);
      FootViewHolder footViewHolder = new FootViewHolder(view);
      return footViewHolder;
    }
    return null;
  }

以上只是控制了Loading布局的出现可隐藏,还要2中状态需要控制就是上面的2个图,一个是正在加载,一个是加载完成状态,这两个状态在adapter里显然是控制不了的,必须要在请求数据的时候才能知道这两种状态,而加载数据又是在activity中执行的,所以我们需要一个用来传递状态的方法:

/**
   * 改变脚布局的状态的方法,在activity根据请求数据的状态来改变这个状态
   *
   * @param state
   */
  public void changeState(int state) {
    this.footer_state = state;
    notifyDataSetChanged();
  }

用来接收状态的变量:

//上拉加载更多
// static final int PULL_LOAD_MORE = 0;
  //正在加载更多
  static final int LOADING_MORE = 1;
  //没有更多
  static final int NO_MORE = 2;
  //脚布局当前的状态,默认为没有更多
  int footer_state = 1;

然后就可以根据这几种状态来控制布局控件的改变了:

 @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;
      }
    }
  }

不要忘了返回的count也要加1,因为添加了一个脚布局:

 @Override
  public int getItemCount() {
    return mList != null ? mList.size() + 1 : 0;
  }

那么什么时候去传递状态到adapter呢?这里就需要给RecyclerView添加滑动监听了,当他滑动到底部的时候显示加载中的状态:

//给recyclerView添加滑动监听
    mRecycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
      @Override
      public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
        /*
        到达底部了,如果不加!isLoading的话到达底部如果还一滑动的话就会一直进入这个方法
        就一直去做请求网络的操作,这样的用户体验肯定不好.添加一个判断,每次滑倒底只进行一次网络请求去请求数据
        当请求完成后,在把isLoading赋值为false,下次滑倒底又能进入这个方法了
         */
        if (newState == RecyclerView.SCROLL_STATE_IDLE && lastVisibleItem + 1 == mAdapter.getItemCount() && !isLoading) {
          //到达底部之后如果footView的状态不是正在加载的状态,就将 他切换成正在加载的状态
          if (page < totlePage) {
            Log.e("duanlian", "onScrollStateChanged: " + "进来了");
            isLoading = true;
            mAdapter.changeState(1);
            new 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();
      }
    });

重点就这几个,下面给出脚布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/ll_below"
        android:layout_width="match_parent"
        android:layout_height="45dp"
  >

  <LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="45dp"
    android:gravity="center"
    android:orientation="horizontal">

    <TextView
      android:id="@+id/tv_line1"
      android:layout_width="60dp"
      android:layout_height="1dp"
      android:layout_marginRight="10dp"
      android:background="#ff00ff"
      android:visibility="gone"/>

    <ProgressBar
      android:id="@+id/progressbar"
      android:layout_width="25dp"
      android:layout_height="25dp"
      android:visibility="visible"/>

    <TextView
      android:id="@+id/foot_view_item_tv"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginLeft="4dp"
      android:text="上拉加载更多"/>

    <TextView
      android:id="@+id/tv_line2"
      android:layout_width="60dp"
      android:layout_height="1dp"
      android:layout_marginLeft="10dp"
      android:background="#ff00ff"
      android:visibility="gone"/>
  </LinearLayout>
</RelativeLayout>

Adapter的代码:

package com.duanlian.recyclerviewloadmoredemo;

import android.content.Context;
import android.graphics.Color;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;

import java.util.List;

public class MyRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
  private Context mContext;
  private List<String> mList;
  //普通布局的type
  static final int TYPE_ITEM = 0;
  //脚布局
  static final int TYPE_FOOTER = 1;
  //  //上拉加载更多
//  static final int PULL_LOAD_MORE = 0;
  //正在加载更多
  static final int LOADING_MORE = 1;
  //没有更多
  static final int NO_MORE = 2;
  //脚布局当前的状态,默认为没有更多
  int footer_state = 1;

  public MyRecyclerAdapter(Context context, List<String> list) {
    mContext = context;
    mList = list;
  }

  @Override
  public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == TYPE_ITEM) {
      View view = View.inflate(mContext, R.layout.item_recycler, null);
      MyViewHolder holder = new MyViewHolder(view);
      return holder;
    } else if (viewType == TYPE_FOOTER) {
      //脚布局
      View view = View.inflate(mContext, R.layout.recycler_load_more_layout, 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;
      }
    }
  }

  @Override
  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 != null ? mList.size() + 1 : 0;
  }

  /**
   * 正常布局的ViewHolder
   */
  class MyViewHolder extends RecyclerView.ViewHolder {
    TextView mTextView;

    public MyViewHolder(View itemView) {
      super(itemView);
      mTextView = (TextView) itemView.findViewById(R.id.item_textView);
    }
  }

  /**
   * 脚布局的ViewHolder
   */
  public static class FootViewHolder extends RecyclerView.ViewHolder {
    private ProgressBar mProgressBar;
    private TextView tv_state;
    private TextView tv_line1;
    private TextView tv_line2;

    public FootViewHolder(View itemView) {
      super(itemView);
      mProgressBar = (ProgressBar) itemView.findViewById(R.id.progressbar);
      tv_state = (TextView) itemView.findViewById(R.id.foot_view_item_tv);
      tv_line1 = (TextView) itemView.findViewById(R.id.tv_line1);
      tv_line2 = (TextView) itemView.findViewById(R.id.tv_line2);

    }
  }

  /**
   * 改变脚布局的状态的方法,在activity根据请求数据的状态来改变这个状态
   *
   * @param state
   */
  public void changeState(int state) {
    this.footer_state = state;
    notifyDataSetChanged();
  }

}

activity中的代码:

package com.duanlian.recyclerviewloadmoredemo;

import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;

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

public class MainActivity extends AppCompatActivity {

  private RecyclerView mRecycler;
  private List<String> mList;
  private List<String> list;
  private MyRecyclerAdapter mAdapter;
  LinearLayoutManager linearLayoutManager;
  int lastVisibleItem;
  int page = 0;
  boolean isLoading = false;//用来控制进入getdata()的次数
  int totlePage = 5;//模拟请求的一共的页数

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

  private void initView() {
    mRecycler = (RecyclerView) findViewById(R.id.recycler);
    linearLayoutManager = new LinearLayoutManager(this);
    mRecycler.setLayoutManager(linearLayoutManager);
    mList = new ArrayList<>();
    mAdapter = new MyRecyclerAdapter(this, mList);
    mRecycler.setAdapter(mAdapter);
    //给recyclerView添加滑动监听
    mRecycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
      @Override
      public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
        /*
        到达底部了,如果不加!isLoading的话到达底部如果还一滑动的话就会一直进入这个方法
        就一直去做请求网络的操作,这样的用户体验肯定不好.添加一个判断,每次滑倒底只进行一次网络请求去请求数据
        当请求完成后,在把isLoading赋值为false,下次滑倒底又能进入这个方法了
         */
        if (newState == RecyclerView.SCROLL_STATE_IDLE && lastVisibleItem + 1 == mAdapter.getItemCount() && !isLoading) {
          //到达底部之后如果footView的状态不是正在加载的状态,就将 他切换成正在加载的状态
          if (page < totlePage) {
            Log.e("duanlian", "onScrollStateChanged: " + "进来了");
            isLoading = true;
            mAdapter.changeState(1);
            new 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();
      }
    });

  }

  /**
   * 模拟请求数据
   */
  private void getData() {
    list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
      list.add("第" + i + "条");
    }
    mList.addAll(list);
    isLoading = false;
    mAdapter = new MyRecyclerAdapter(this, mList);
    mRecycler.setAdapter(mAdapter);
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • android RecyclerView侧滑菜单,滑动删除,长按拖拽,下拉刷新上拉加载

    本文介绍的库中的侧滑效果借鉴自SwipeMenu,并对SipwMenu的源码做了修改与Bug修复,然后才开发出的SwipeRecyclerView. 需要说明的是,本库没有对RecyclerView做大的修改,只是ItemView的封装.看起来是对RecyclerView的修改,其实仅仅是为RecyclerView添加了使用的方法API而已. 本库已经更新了三个版本了,会一直维护下去,根据小伙伴的要求,以后也会添加一些其它功能. SwipeRecyclerView将完美解决这些问题: 以下功能全

  • Android RecyclerView实现下拉刷新和上拉加载更多

    使用官方的刷新控件SwipeRefreshLayout来实现下拉刷新,当RecyclerView滑到底部实现下拉加载(进度条效果用RecyclerView加载一个布局实现) 需要完成控件的下拉监听和上拉监听,其中,下拉监听通过SwipRefreshLayout的setOnRefreshListener()方法监听,而上拉刷新,需要通过监听列表的滚动,当列表滚动到底部时触发事件,具体代码如下 主布局 <?xml version="1.0" encoding="utf-8&

  • RecyclerView上拉加载封装代码

    RecyclerView上拉加载,先看效果: 网上有很多这类得框架,不过在自己的项目只用到上拉加载的功能,所以自己封装一个简单点的. 主要依赖BaseRecyPRAdapter这类 public abstract class BaseRecyPRAdapter<T> extends RecyclerView.Adapter<BaseRecyPRAdapter.BaseViewHolder> { private static final String TAG = "Base

  • Android使用recyclerview打造真正的下拉刷新上拉加载效果

    前言 前段时间需要用到recyclerview,就想找个封装好的下拉刷新,上拉加载的库,结果愣是没找到,便自己写了一个. 注意:我说的是"上拉加载",不是滑到底部自动加载. 虽然现在自动加载是主流和趋势,但也不排除有时候就需要用到上拉加载啊,毕竟林子大了,什么样的产品经理都有对吧. 代码写好后,准备发布到bintray的时候,向同事征求这个项目的名字,同事说:"就叫DZTRecyclerview!" 不解,同事解释:"叼炸天Recyclerview!&qu

  • Android RecyclerView上拉加载更多功能回弹实现代码

    实现原理是使用RecyclerView的OnTouchListener方法监听滑动 在adapter里面增加两项footview 其中date.size为显示的加载条,可以自定义,date.size+1为空白的View,我们设置其高度为0 我们通过LinearLayoutManager的 findLastVisibleItemPosition判断显示的最后一条数据,如果是空白view,表示加载条已经完全展示,松开即可刷新. 回弹效果是通过在滑动时动态改变空白view的高度,达到阻尼效果 ,回弹时

  • Android RecyclerView添加上拉加载更多功能

    上一篇文章已经介绍了如何为RecyclerView添加FootView,在此基础上,要添加分页加载的功能其实已经很简单了. 上一篇文章地址:为RecyclerView添加FootView和HeadView 效果:(源码在文章结尾) 实现关键 在上一篇代码的基础上,只需要在onBindViewHolder(ViewHolder holder, int position)函数中添加一定修改就可以了,如下: @Override public void onBindViewHolder(ViewHold

  • Android RecyclerView下拉刷新和上拉加载更多

    今天终于有点时间,来写了一下: 为RecyclerView实现下拉刷新和上拉加载更多.今天会在前面的两篇文章的基础上: RecyclerView系列之(1):为RecyclerView添加Header和Footer RecyclerView系列之(2):为RecyclerView添加分隔线 继续讲述RecyclerView中一些常用组件的实现下拉刷新和上拉加载更多的功能. 在现在的Android手机应用中,几乎每一个APP都有下拉刷新和上拉加载更多的功能,它们的重要性不言而喻. 先不多说,先看效

  • Android RecyclerView实现下拉刷新和上拉加载

    RecyclerView已经出来很久了,许许多多的项目都开始从ListView转战RecyclerView,那么,上拉加载和下拉刷新是一件很有必要的事情. 在ListView上,我们可以通过自己添加addHeadView和addFootView去添加头布局和底部局实现自定义的上拉和下拉,或者使用一些第三方库来简单的集成,例如Android-pulltorefresh或者android-Ultra-Pull-to-Refresh,后者的自定义更强,但需要自己实现上拉加载. 而在下面我们将用两种方式

  • Android中使用RecyclerView实现下拉刷新和上拉加载

    推荐阅读:使用RecyclerView添加Header和Footer的方法                       RecyclerView的使用之HelloWorld RecyclerView 是Android L版本中新添加的一个用来取代ListView的SDK,它的灵活性与可替代性比listview更好.本文给大家介绍如何为RecyclerView添加下拉刷新和上拉加载,过去在ListView当中添加下拉刷新和上拉加载是非常方便的利用addHeaderView和addFooterVie

  • Android RecyclerView 上拉加载更多及下拉刷新功能的实现方法

    RecyclerView 已经出来很久了,但是在项目中之前都使用的是ListView,最近新的项目上了都大量的使用了RecycleView.尤其是瀑布流的下拉刷新,网上吧啦吧啦没有合适的自己总结了一哈. 先贴图上来看看: 使用RecyclerView实现上拉加载更多和下拉刷新的功能我自己有两种方式: 1.使用系统自带的Android.support.v4.widget.SwipeRefreshLayout这个控价来实现. 2.自定义的里面带有RecyleView的控件. 使用RecycleVie

随机推荐