欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2024-03-02 19:19:10
recyclerview已经出来很久了,许许多多的项目都开始从listview转战recyclerview,那么,上拉加载和下拉刷新是一件很有必要的事情。 在listvi...

recyclerview已经出来很久了,许许多多的项目都开始从listview转战recyclerview,那么,上拉加载和下拉刷新是一件很有必要的事情。

在listview上,我们可以通过自己添加addheadview和addfootview去添加头布局和底部局实现自定义的上拉和下拉,或者使用一些第三方库来简单的集成,例如android-pulltorefresh或者android-ultra-pull-to-refresh,后者的自定义更强,但需要自己实现上拉加载。

而在下面我们将用两种方式来实现上拉加载和下拉刷新

第一种方式:swiperefreshlayout+滑动底部自动加载

第二种方式:使用第三方库swipetoloadlayout实现上拉加载和下拉刷新。

第一种方式:swiperefreshlayout+滑动底部自动加载

swiperefreshlayout实现很简单,重点是滑动到底部自动加载应该如何实现,其实其实现的方式类似于listview的实现方式。

看一下activity_recycle_swiperefresh.xml文件:

<android.support.v4.widget.swiperefreshlayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/swipe_refresh"
 android:orientation="vertical" android:layout_width="match_parent"
 android:layout_height="match_parent">

 <android.support.v7.widget.recyclerview
  android:id="@+id/swipe_target"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:scrollbars="none" />

</android.support.v4.widget.swiperefreshlayout>

布局文件就两个控件,swiperefreshlayout中嵌套recyclerview。

在代码中初始化recyclerview以及实现adapter等,这不是重点,不再贴代码。

在recyclerview中有方法addonscrolllistener,该方法类似于listview的setonscrolllistener方法,onscrolllistener中有两个方法的回调

*onscrolled(recyclerview recyclerview, int dx, int dy) :滚动的回调,dx和dy表示手指滑动水平和垂直的偏移量。

*onscrollstatechanged(recyclerview recyclerview, int newstate):滑动状态的回调。

那么,我们的着重点就在这个两个方法上了。

对于向上加载更多,我们需要有如下判断

--是否是向上滑动

--是否滑动到底部

--当前是否正在加载数据

--当前状态是否是滑动停止的状态

实现比较复杂,定义一个类loaddatascrollcontroller,继承类recyclerview.onscrolllistener,

因为onscrollstatechanged实在状态改变时的回调,无法时时的获取显示的条目以及位置,所以我们在onscrolled中获取相应位置,

 @override
 public void onscrolled(recyclerview recyclerview, int dx, int dy) {

  /**
   * 获取布局参数
   */
  recyclerview.layoutmanager layoutmanager = recyclerview.getlayoutmanager();

  //如果为null,第一次运行,确定布局类型
  if (mlayoutmanagertype == null) {
   if (layoutmanager instanceof linearlayoutmanager) {
    mlayoutmanagertype = layoutmanagertype.linear_layout;
   } else if (layoutmanager instanceof gridlayoutmanager) {
    mlayoutmanagertype = layoutmanagertype.grid_layout;
   } else if (layoutmanager instanceof staggeredgridlayoutmanager) {
    mlayoutmanagertype = layoutmanagertype.staggered_grid_layout;
   } else {
    throw new runtimeexception("layoutmanager should be linearlayoutmanager,gridlayoutmanager,staggeredgridlayoutmanager");
   }
  }

  //对于不太能够的布局参数,不同的方法获取到当前显示的最后一个条目数
  switch (mlayoutmanagertype) {
   case linear_layout:
    mlastvisibleitemposition = ((linearlayoutmanager) layoutmanager).findlastvisibleitemposition();
    break;
   case grid_layout:
    mlastvisibleitemposition = ((gridlayoutmanager) layoutmanager).findlastvisibleitemposition();
    break;
   case staggered_grid_layout:
    staggeredgridlayoutmanager staggeredgridlayoutmanager = (staggeredgridlayoutmanager) layoutmanager;
    if (mlastpostions == null) {
     mlastpostions = new int[staggeredgridlayoutmanager.getspancount()];
    }
    staggeredgridlayoutmanager.findlastvisibleitempositions(mlastpostions);
    mlastvisibleitemposition = findmax(mlastpostions);
    break;
   default:
    break;
  }

 }

首先获取布局管理器,并判断是那种类型的,因为有三种类型,定义枚举来保存布局类型的参数

/**
 *
 * recycleview的布局管理器的类型
 * created by alex_mahao on 2016/5/10.
 */
public enum layoutmanagertype {
 linear_layout,
 grid_layout,
 staggered_grid_layout
}

然后根据布局惯例其的类型获取其当前显示的最大条目,对于瀑布流来说,他如果是垂直的两列瀑布的话,我们需要获取两列中分别最大条目数,进行比较,选出最大条目数。

 /**
  * 当是瀑布流时,获取到的是每一个瀑布最下方显示的条目,通过条目进行对比
  */
 private int findmax(int[] lastpositions) {
  int max = lastpositions[0];
  for (int value : lastpositions) {
   if (value > max) {
    max = value;
   }
  }
  return max;
 }

拿到当前最大的条目数之后,在onscrollstatechange中进行判断状态等,

 @override
 public void onscrollstatechanged(recyclerview recyclerview, int newstate) {

  recyclerview.layoutmanager layoutmanager = recyclerview.getlayoutmanager();

  //recycleview 显示的条目数
  int visiblecount = layoutmanager.getchildcount();

  //显示数据总数
  int totalcount = layoutmanager.getitemcount();


  // 四个条件,分别是是否有数据,状态是否是滑动停止状态,显示的最大条目是否大于整个数据(注意偏移量),是否正在加载数据
  if(visiblecount>0
    &&newstate==recyclerview.scroll_state_idle
    &&mlastvisibleitemposition>=totalcount-1
    &&!isloaddata){
   //可以加载数据
   isloaddata = true;
  }

 }

注释很清楚,在加载数据的地方,我们将isloaddata设为true,同时利用接口回调加载数据,等数据加载完成,通过setloaddatastatus方法设置为false

 public void setloaddatastatus(boolean isloaddata){
  this.isloaddata = isloaddata;
 }

如果这样就结束了,感觉很麻烦,对于刷新和加载更多,我们需要在调用的地方分别设置监听,那么我们可以让loaddatascrollcontroller实现swiperefreshlayout的刷新监听方法,在利用我们定义的统一的上拉刷新和加载数据接口进行处理

/**
 * 实现上拉加载的监听:加载条件:滑动到最后,且是停止状态,则开始加载数据
 * created by alex_mahao on 2016/5/10.
 */
public class loaddatascrollcontroller extends recyclerview.onscrolllistener implements swiperefreshlayout.onrefreshlistener {

 /**
  * 当前布局管理器的类型
  */
 private layoutmanagertype mlayoutmanagertype;


 /**
  * 当前recycleview显示的最大条目
  */
 private int mlastvisibleitemposition;


 /**
  * 每列的最后一个条目
  */
 private int[] mlastpostions;


 /**
  * 是否正在加载数据 包括刷新和向上加载更多
  */
 private boolean isloaddata = false;


 /**
  * 回调接口
  */
 private onrecyclerefreshlistener mlistener;


 public loaddatascrollcontroller(onrecyclerefreshlistener onrecyclerefreshlistener) {
  this.mlistener = onrecyclerefreshlistener;
 }

 @override
 public void onscrolled(recyclerview recyclerview, int dx, int dy) {

  /**
   * 获取布局参数
   */
  recyclerview.layoutmanager layoutmanager = recyclerview.getlayoutmanager();

  //如果为null,第一次运行,确定布局类型
  if (mlayoutmanagertype == null) {
   if (layoutmanager instanceof linearlayoutmanager) {
    mlayoutmanagertype = layoutmanagertype.linear_layout;
   } else if (layoutmanager instanceof gridlayoutmanager) {
    mlayoutmanagertype = layoutmanagertype.grid_layout;
   } else if (layoutmanager instanceof staggeredgridlayoutmanager) {
    mlayoutmanagertype = layoutmanagertype.staggered_grid_layout;
   } else {
    throw new runtimeexception("layoutmanager should be linearlayoutmanager,gridlayoutmanager,staggeredgridlayoutmanager");
   }
  }

  //对于不太能够的布局参数,不同的方法获取到当前显示的最后一个条目数
  switch (mlayoutmanagertype) {
   case linear_layout:
    mlastvisibleitemposition = ((linearlayoutmanager) layoutmanager).findlastvisibleitemposition();
    break;
   case grid_layout:
    mlastvisibleitemposition = ((gridlayoutmanager) layoutmanager).findlastvisibleitemposition();
    break;
   case staggered_grid_layout:
    staggeredgridlayoutmanager staggeredgridlayoutmanager = (staggeredgridlayoutmanager) layoutmanager;
    if (mlastpostions == null) {
     mlastpostions = new int[staggeredgridlayoutmanager.getspancount()];
    }
    staggeredgridlayoutmanager.findlastvisibleitempositions(mlastpostions);
    mlastvisibleitemposition = findmax(mlastpostions);
    break;
   default:
    break;
  }

 }

 @override
 public void onscrollstatechanged(recyclerview recyclerview, int newstate) {

  recyclerview.layoutmanager layoutmanager = recyclerview.getlayoutmanager();

  //recycleview 显示的条目数
  int visiblecount = layoutmanager.getchildcount();

  //显示数据总数
  int totalcount = layoutmanager.getitemcount();


  // 四个条件,分别是是否有数据,状态是否是滑动停止状态,显示的最大条目是否大于整个数据(注意偏移量),是否正在加载数据
  if(visiblecount>0
    &&newstate==recyclerview.scroll_state_idle
    &&mlastvisibleitemposition>=totalcount-1
    &&!isloaddata){
   //可以加载数据
   if(mlistener!=null){
    isloaddata = true;
    mlistener.loadmore();
   }
  }

 }


 /**
  * 当是瀑布流时,获取到的是每一个瀑布最下方显示的条目,通过条目进行对比
  */
 private int findmax(int[] lastpositions) {
  int max = lastpositions[0];
  for (int value : lastpositions) {
   if (value > max) {
    max = value;
   }
  }
  return max;
 }


 public void setloaddatastatus(boolean isloaddata){
  this.isloaddata = isloaddata;
 }

 @override
 public void onrefresh() {
  //刷新数据的方法
  if(mlistener!=null){
   isloaddata = true;
   mlistener.refresh();
  }

 }

 /**
  * 数据加载接口回调
  */
 interface onrecyclerefreshlistener{
  void refresh();
  void loadmore();
 }
}

最后看一下main的代码

/**
 * 使用原生的swiperefreshlayout和代码判断
 *  实现recyclewview 的刷新和加载更多
 *
 * created by alex_mahao on 2016/5/10.
 */
public class swiperefreshactivity extends appcompatactivity implements loaddatascrollcontroller.onrecyclerefreshlistener {


 private swiperefreshlayout mswiperefresh;

 private recyclerview mrecycle;

 private homeadapter madapter;

 private loaddatascrollcontroller mcontroller;


 private progressdialog pd;

 @override
 protected void oncreate(@nullable bundle savedinstancestate) {
  super.oncreate(savedinstancestate);

  setcontentview(r.layout.activity_recycle_swiperefresh);

  mrecycle = ((recyclerview) findviewbyid(r.id.swipe_target));

  mswiperefresh = ((swiperefreshlayout) findviewbyid(r.id.swipe_refresh));

  mswiperefresh.setcolorschemecolors(color.red,color.green,color.blue);

  /**
   * 创建控制器,同时使当前activity实现数据监听回调接口
   */
  mcontroller = new loaddatascrollcontroller(this);



  madapter = new homeadapter();

  //设置垂直的线性布局管理器,orientation --> vertical:垂直 horizontal:水平
  linearlayoutmanager layoutmanager = new linearlayoutmanager(this);
  layoutmanager.setorientation(linearlayoutmanager.vertical);

  //staggeredgridlayoutmanager layoutmanager = new staggeredgridlayoutmanager(2,staggeredgridlayoutmanager.vertical);

  //添加分割线
  mrecycle.additemdecoration(new divideritemdecoration(getapplicationcontext(), divideritemdecoration.vertical_list));


  mrecycle.setlayoutmanager(layoutmanager);

  mrecycle.setitemanimator(new defaultitemanimator());

  mrecycle.setadapter(madapter);

  madapter.refresh();

  /**
   * 设置监听
   */
  mrecycle.addonscrolllistener(mcontroller);

  mswiperefresh.setonrefreshlistener(mcontroller);

 }

 @override
 public void refresh() {
  //刷新的接口调
  mswiperefresh.postdelayed(new runnable() {
   @override
   public void run() {
    madapter.refresh();
    mswiperefresh.setrefreshing(false);
    mcontroller.setloaddatastatus(false);
   }
  },2000);
 }

 @override
 public void loadmore() {
  //加载更多的接口回调
  pd = new progressdialog(this);
  pd.show();
  mswiperefresh.postdelayed(new runnable() {
   @override
   public void run() {
    madapter.add();
    //设置数据加载结束的监听状态
    mcontroller.setloaddatastatus(false);
    pd.dismiss();
   }
  },2000);
 }
}

贴个效果图

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

第二种方式:swipetoloadlayout实现上拉加载和下拉刷新

该刷新控件的方式类似于ultra-pull-to-refresh的使用方式。

如下方式添加该库:

 repositories {
  maven { url "https://jitpack.io" }
   }

 compile 'com.github.aspsine:swipetoloadlayout:1.0.3'

首先我们需要自定义一个头视图和底部视图,头部试图和底部试图的用法相同,所以我们先定义一个头部视图类:

/**
 * 基础的refreshheadview
 */
public class refreshheaderview extends textview implements swiperefreshtrigger, swipetrigger {

 public refreshheaderview(context context) {
  super(context);
 }

 public refreshheaderview(context context, attributeset attrs) {
  super(context, attrs);
 }

 public refreshheaderview(context context, attributeset attrs, int defstyleattr) {
  super(context, attrs, defstyleattr);
 }

 @targetapi(build.version_codes.lollipop)
 public refreshheaderview(context context, attributeset attrs, int defstyleattr, int defstyleres) {
  super(context, attrs, defstyleattr, defstyleres);
 }

 @override
 public void onrefresh() {
  //下拉到一定位置松开之后,调用此方法
  settext("refresh");

  log.i("info","onrefresh");
 }

 @override
 public void onprepare() {

  //下拉之前调用此方法
  log.i("info","onprepare");
 }

 @override
 public void onmove(int yscrolled, boolean iscomplete, boolean automatic) {
  if (!iscomplete) {
   //当前y轴偏移量大于控件高度时,标识下拉到界限,显示“松开已刷新”
   if (yscrolled >= getheight()) {

   } else {
    //未达到偏移量

   }
  } 
  log.i("info","onmove");
 }

 @override
 public void onrelease() {
  //达到一定滑动距离,松开刷新时调用
  settext("onrelease");
  log.i("info","onrelease");
 }

 @override
 public void oncomplete() {
  //加载完成之后调用此方法
  settext("complete");
  log.i("info","oncomplete");
 }

 @override
 public void onreset() {
  //重置
  settext("onreset");
  log.i("info","onreset");
 }
}

其需要实现接口swiperefreshtrigger和swipetrigger。

而底部需要实现swipetrigger和swipeloadmoretrigger。

布局文件中如下使用

<relativelayout 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"
 android:background="#ecedf0"
 >

 <com.aspsine.swipetoloadlayout.swipetoloadlayout
  android:id="@+id/swipetoloadlayout"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

  <com.mahao.alex.systemwidgetdemo.recycleview.swipetoloadlayout.refreshheaderview
   android:id="@+id/swipe_refresh_header"
   android:layout_width="match_parent"
   android:layout_height="wrap_content" />

  <android.support.v7.widget.recyclerview
   android:id="@+id/swipe_target"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:scrollbars="vertical" />

  <com.mahao.alex.systemwidgetdemo.recycleview.swipetoloadlayout.loadermoreview
   android:id="@+id/swipe_load_more_footer"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:gravity="center"
   android:padding="20dp" />
 </com.aspsine.swipetoloadlayout.swipetoloadlayout>


</relativelayout>

查找控件,设置监听

        swipetoloadlayout.setonrefreshlistener(this);
        swipetoloadlayout.setonloadmorelistener(this);

在我们之前的代码中,加入了log信息,我们可以看一下log信息。…代表多次onmove()方法多次调用。

05-10 10:30:34.396 23814-23814/com.mahao.alex.systemwidgetdemo i/info: onprepare
05-10 10:30:34.536 23814-23814/com.mahao.alex.systemwidgetdemo i/info: onmove
..........................................................................
05-10 10:30:34.886 23814-23814/com.mahao.alex.systemwidgetdemo i/info: onmove
05-10 10:30:34.896 23814-23814/com.mahao.alex.systemwidgetdemo i/info: onrelease
05-10 10:30:34.906 23814-23814/com.mahao.alex.systemwidgetdemo i/info: onmove
..........................................................................
05-10 10:30:35.086 23814-23814/com.mahao.alex.systemwidgetdemo i/info: onmove
05-10 10:30:35.106 23814-23814/com.mahao.alex.systemwidgetdemo i/info: onrefresh
05-10 10:30:37.116 23814-23814/com.mahao.alex.systemwidgetdemo i/info: oncomplete
05-10 10:30:37.416 23814-23814/com.mahao.alex.systemwidgetdemo i/info: onmove
..........................................................................
05-10 10:30:37.516 23814-23814/com.mahao.alex.systemwidgetdemo i/info: onmove
05-10 10:30:37.916 23814-23814/com.mahao.alex.systemwidgetdemo i/info: onreset

首先会调用onprepare()方法,onmove()方法会一直调用,只要视图有偏移,就会调用。下拉到一定距离之后,松开调用onrelaease(),回归到刷新位置时回调onrefresh(),加载完成调用oncomplete(),视图开始缩小,最后隐藏之后调用onreset()

根据需求自定义视图,

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

定义我们的椭圆,使用自定义控件

/**
 * circleview 圆盘控件,可以旋转
 * created by alex_mahao on 2016/5/10.
 */
public class circleview extends view {

 /**
  * 控件的半径
  */
 private int mradius;

 /**
  * 绘制弧形的画笔
  */
 private paint marcpaint;

 /**
  * 绘制弧形的区域
  */
 private rectf mrange;


 private int[] colors = {color.red, color.blue, color.yellow, color.green};

 public circleview(context context) {
  this(context, null, 0);
 }

 public circleview(context context, attributeset attrs) {
  this(context, attrs, 0);
 }

 public circleview(context context, attributeset attrs, int defstyleattr) {
  super(context, attrs, defstyleattr);

  init();
 }

 private void init() {
  marcpaint = new paint();
  marcpaint.setantialias(true);
  marcpaint.setdither(true);
  marcpaint.setstyle(paint.style.fill);
 }

 @override
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
  super.onmeasure(widthmeasurespec, heightmeasurespec);

  int width = 0;
  int height = 0;

  int widthsize = measurespec.getsize(widthmeasurespec);
  int widthmode = measurespec.getmode(widthmeasurespec);

  int heightsize = measurespec.getsize(heightmeasurespec);
  int heightmode = measurespec.getmode(heightmeasurespec);


  if (widthmode == measurespec.exactly) {
   width = widthsize;
  } else {
   width = (int) typedvalue.applydimension(typedvalue.complex_unit_dip, 45, getresources().getdisplaymetrics());
  }

  if (heightmode == measurespec.exactly) {
   height = heightsize;
  } else {
   height = (int) typedvalue.applydimension(typedvalue.complex_unit_dip, 45, getresources().getdisplaymetrics());
  }

  //获取半径
  mradius = math.min(width, height) / 2;
  /**
   * 设置宽高为固定值
   */
  setmeasureddimension(mradius * 2, mradius * 2);

   mrange = new rectf(0, 0, mradius * 2, mradius * 2);
 }


 @override
 protected void ondraw(canvas canvas) {

  float degree = 360/colors.length/2f;

  for (int i = 0; i < 8; i++) {
   marcpaint.setcolor(colors[i%4]);
   canvas.drawarc(mrange,-90f+degree*i,degree,true,marcpaint);
  }

 }
}

绘制头部刷新试图

**
 * 自定义的下拉刷新控件 头部
 * created by alex_mahao on 2016/5/10.
 */
public class circlerefreshheaderview extends relativelayout implements swipetrigger, swiperefreshtrigger {

 circleview mcircleview;

 textview mdesctext;

 private objectanimator anim;

 private boolean isrelease;

 public circlerefreshheaderview(context context) {
  this(context, null, 0);
 }

 public circlerefreshheaderview(context context, attributeset attrs) {
  this(context, attrs, 0);
 }

 public circlerefreshheaderview(context context, attributeset attrs, int defstyleattr) {
  super(context, attrs, defstyleattr);

  initview();
 }

 /**
  * 初始化布局
  */
 private void initview() {

  int circlewidth = (int) typedvalue.applydimension(typedvalue.complex_unit_dip, 30, getresources().getdisplaymetrics());

  mcircleview = new circleview(getcontext());

  linearlayout.layoutparams circleparams = new linearlayout.layoutparams(circlewidth,circlewidth);

  mcircleview.setlayoutparams(circleparams);

  mdesctext = new textview(getcontext());

  linearlayout.layoutparams descparams = new linearlayout.layoutparams(circlewidth*3, viewgroup.layoutparams.wrap_content);

  descparams.gravity = gravity.center;
  descparams.setmargins(circlewidth/2,0,0,0);
  mdesctext.setlayoutparams(descparams);
  mdesctext.settextsize(12);
  mdesctext.settextcolor(color.gray);
  mdesctext.settext("下拉刷新");

  //添加线性的父布局
  linearlayout ll = new linearlayout(getcontext());
  relativelayout.layoutparams llparams = new layoutparams(viewgroup.layoutparams.wrap_content, viewgroup.layoutparams.wrap_content);
  llparams.addrule(center_in_parent);
  ll.setlayoutparams(llparams);
  ll.setpadding(10,10,10,10);

  ll.addview(mcircleview);
  ll.addview(mdesctext);

  addview(ll);
 }

 @override
 public void onrefresh() {

  //开始刷新,启动动画
  anim = objectanimator.offloat(mcircleview, "rotation", mcircleview.getrotation(), mcircleview.getrotation()+360f)
    .setduration(500);
  anim.setrepeatcount(valueanimator.infinite);
  anim.setrepeatmode(valueanimator.restart);
  anim.start();

  mdesctext.settext("正在加载数据");
 }

 @override
 public void onprepare() {
  isrelease = false;
 }

 @override
 public void onmove(int yscroll, boolean iscomplete, boolean b1) {
  if (!iscomplete) {
   if (yscroll < getheight()) {
    mdesctext.settext("下拉刷新");
   } else {
    mdesctext.settext("松开刷新更多");
   }

   //如果是仍在下拉状态,则圆环跟随滑动进行滚动
   if (!isrelease)
    mcircleview.setrotation(((float) yscroll) / getheight() * 360f);
  }


 }

 @override
 public void onrelease() {
  isrelease = true;
 }

 @override
 public void oncomplete() {
  anim.cancel();
  mdesctext.settext("加载完成");
 }

 @override
 public void onreset() {
  //重置时,将动画置为初始状态
  mcircleview.setrotation(0f);
 }
}

布局文件

<relativelayout 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"
 android:background="#ecedf0"
 >

 <com.aspsine.swipetoloadlayout.swipetoloadlayout
  android:id="@+id/swipetoloadlayout"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

  <com.mahao.alex.systemwidgetdemo.recycleview.swipetoloadlayout.circlerefreshheaderview
   android:id="@+id/swipe_refresh_header"
   android:layout_width="match_parent"
   android:layout_height="wrap_content" />

  <android.support.v7.widget.recyclerview
   android:id="@+id/swipe_target"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:scrollbars="vertical" />

  <com.mahao.alex.systemwidgetdemo.recycleview.swipetoloadlayout.loadermoreview
   android:id="@+id/swipe_load_more_footer"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:gravity="center"
   android:padding="20dp" />
 </com.aspsine.swipetoloadlayout.swipetoloadlayout>


</relativelayout>

public class swipetolayoutactivity extends appcompatactivity implements onrefreshlistener, onloadmorelistener {



 private recyclerview mrecycleview;

 swipetoloadlayout swipetoloadlayout;

 private homeadapter adapter;


 @override
 protected void oncreate(@nullable bundle savedinstancestate) {
  super.oncreate(savedinstancestate);
  setcontentview(r.layout.activity_recycle_swipetolayout);


  swipetoloadlayout = ((swipetoloadlayout) findviewbyid(r.id.swipetoloadlayout));


  mrecycleview = ((recyclerview) findviewbyid(r.id.swipe_target));


  adapter = new homeadapter();

  //设置垂直的线性布局管理器,orientation --> vertical:垂直 horizontal:水平
  linearlayoutmanager layoutmanager = new linearlayoutmanager(this);
  layoutmanager.setorientation(linearlayoutmanager.vertical);

//  staggeredgridlayoutmanager layoutmanager = new staggeredgridlayoutmanager(2,staggeredgridlayoutmanager.vertical);

  //添加分割线
  mrecycleview.additemdecoration(new divideritemdecoration(getapplicationcontext(), divideritemdecoration.vertical_list));

  mrecycleview.setlayoutmanager(layoutmanager);

  mrecycleview.setitemanimator(new defaultitemanimator());

  mrecycleview.setadapter(adapter);

  adapter.refresh();

  /**
   * 设置下拉刷新和上拉加载监听
   */
  swipetoloadlayout.setonrefreshlistener(this);
  swipetoloadlayout.setonloadmorelistener(this);

 }




 @override
 public void onrefresh() {
  swipetoloadlayout.postdelayed(new runnable() {
   @override
   public void run() {
    adapter.refresh();
    swipetoloadlayout.setrefreshing(false);
   }
  },2000);
 }

 @override
 public void onloadmore() {
  swipetoloadlayout.postdelayed(new runnable() {
   @override
   public void run() {

    adapter.add();
    swipetoloadlayout.setloadingmore(false);
   }
  },2000);
 }
}

ok。肯定有小伙伴使用该框架时一直报错,为什么,看框架的源码,有如下一段

this.mheaderview = this.findviewbyid(id.swipe_refresh_header);
 this.mtargetview = this.findviewbyid(id.swipe_target);
 this.mfooterview = this.findviewbyid(id.swipe_load_more_footer);

可以看出,作者是根据固定的id值获取的,所以在我们的布局文件中,必须使用固定的三个id。

如有需求,可移步我的github获取源码,源码在systemwidgetdemo中。

以上就是本文的全部内容,希望对大家学习android软件编程有所帮助。