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

Android RecyclerView实现下拉刷新和上拉加载,第1张

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

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 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,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); }}

贴个效果图

第二种方式: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,int defStyleAttr,int defStyleRes) {  super(context,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()

根据需求自定义视图,

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

/** * 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,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,getResources().getdisplayMetrics());  }  //获取半径  mRadius = Math.min(wIDth,height) / 2;  /**   * 设置宽高为固定值   */  setMeasuredDimension(mRadius * 2,mRadius * 2);   mRange = new RectF(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,0); } public CircleRefreshheaderVIEw(Context context,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);  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);  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 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软件编程有所帮助。

总结

以上是内存溢出为你收集整理的Android RecyclerView实现下拉刷新和上拉加载全部内容,希望文章能够帮你解决Android RecyclerView实现下拉刷新和上拉加载所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1141519.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存