Android代码实现AdapterViews和RecyclerView无限滚动

应用的一个共同的特点就是当用户欢动时自动加载更多的内容,这是通过用户滑动触发一定的阈值时发送数据请求实现的。
相同的是:信息实现滑动的效果需要定义在列表中最后一个可见项,和某些类型的阈值以便于开始在最后一项到达之前开始抓取数据,实现无限的滚动。
实现无限滚动的现象的重要之处就在于在用户滑动到最低端之前就行数据的获取,所以需要加上一个阈值来帮助实现获取数据的预期。

使用ListView和GridView实现

每个AdapterView 例如ListView 和GridView 当用户开始进行滚动操作时候都会触发OnScrollListener .使用这个系统我们就可以定义一个基本的EndlessScrollListener ,通过创造继承OnScrollListener 的类来支持大多数情况下的使用。

package com.codepath.customadapter;

import android.widget.AbsListView;

/**
 * Created by Administrator on 2016/7/11.
 */
public abstract class EndlessScrollListener implements AbsListView.OnScrollListener {
 //在你滑动项下最少为多少时开始加载数据
 private int visibleThreshold = 5;
 //已经加载数据的当前页码
 private int currentPage = 0;
 //上一次加载数据后数据库的数据量
 private int previousTotalItemCount = 0;
 //我们是否在等待最后一组数据的加载
 private boolean loading = true;
 //设置开始页的下标
 private int startingPageIndex = 0;
 public EndlessScrollListener() {

 }
 public EndlessScrollListener(int visibleThreshold) {
  this.visibleThreshold = visibleThreshold;
 }
 public EndlessScrollListener(int visibleThreshold, int startingPageIndex) {
  this.visibleThreshold = visibleThreshold;
  this.startingPageIndex = startingPageIndex;
 }
 //这个方法可能会在滑动调用很多次,所以在设计时要保持谨慎
 //我们需要一些有用的参数来帮助我们,当我们需要加载更多数据的时候
 //但是我们首先要检查是否我们在等待先前的加载结束

//onScroll()当列表或网格视图被滚动后将会调用,参数一:报告状态的视图参数二:第一个可以看见的项的下标,参数三:可见项的数量参数四:listAdapter中所有的项数
 @Override
 public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

  //如果总项数为0,而且先前没有项,那么这个列表是无效的应该被设定为初始状态
  if (totalItemCount < previousTotalItemCount) {
   this.currentPage = this.startingPageIndex;
   this.previousTotalItemCount = totalItemCount;
   if (totalItemCount == 0) {this.loading = true;}
  }
  //如果仍在加载中我们可以检查一下数据集合是否改变了,如果改变的话那就是已经完成了loading需要更新当前
  //页数和数据总量
  if (loading && (totalItemCount > previousTotalItemCount)) {
   loading = false;
   previousTotalItemCount = totalItemCount;
   currentPage++;
  }
  //如果当前没有加载,我们需要检查当前是否达到了阈值,如果是的话我们需要
  //加载更多的数据,执行onLoadMore
  if (!loading && (firstVisibleItem + visibleItemCount + visibleThreshold) >= totalItemCount) {
   loading = onLoadMore(currentPage + 1, totalItemCount);
  }
 }
 //定义实际加载数据的过程,如果数据加载完成返回false,如果正在加载返回true;
 public abstract boolean onLoadMore(int page, int totalItemCount);

 @Override
 public void onScrollStateChanged(AbsListView view, int scrollState) {
  //不采取动作
 }
}

要注意的是这是一个抽象的类,为了要使用这些,必须继承这个基本的类并且实现onLoadMore()方法实际的获取数据, 我们在一个活动中定义一个匿名的类来继承EndlessScrollListener然后将其连接AdapterView上

public class MainActivity extends Activity {
 @Override
 protected void onCreate(Bundle savedInstance) {
  //向平常一样
   ListView lvItems = (ListView) findViewById(R.id.lvItens);
   //将监听器绑定到上面
    lvItems.setOnScrollListener(new EndlessScrollListener() {
   @Override
   public boolean onLoadMore(int page, int totalItemsCount) {
    // 当新数据需要绑定到列表上的时候触发
    // 加载数据需要的代码Add whatever code is needed to append new items to your AdapterView
    customLoadMoreDataFromApi(page);
    // or customLoadMoreDataFromApi(totalItemsCount);
    return true; //数据加载中为true,不然为false; ONLY if more data is actually being loaded; false otherwise.
   }
  });
 }
 //加载更多的数据
 public void customLoadMoreDataFromApi(int offset) {
  //这个方法通常会发起一些网络请求,然后向适配器添加更多的数据
  //将偏移量数据作为参数附在请求里来获得一个数据的分页
  //解析API返回的值并且获得新的对象构建适配器
 }
}

现在当用户滑动并且触发阈值时会自动触发onloadMore() 方法,而且监听器给予了对于页数和数据总量的访问权限。

实现RecyclerView的无限滑动

我们可以使用相同的方法来定义一个接口EndlessRecyclerViewScrollListener 然后定义一个onLoadMore() 的方法来进行实现。由于LayoutManager负责项的生成和滑动的管理,我们需要一个LayoutManage的实例来收集必要的信息。
实现必要的分页需要这样的步骤:
1).直接复制EndlessRecyclerViewScrollListener.java
2).调用addOnScrollListener(...) 在RecyclerView 中来实现无限的分页,传递EndlessRecyclerViewScrollListener的实例来实现onLoadMore 方法来决定什么时候来加载新的数据
3).在onLoadMore 方法中通过发送网络请求或者从源数据加载来获得更多item。

 protected void onCreate(Bundle savedInstanceState) {
  // Configure the RecyclerView获得RecylerView的实例
  RecyclerView rvItems = (RecyclerView) findViewById(R.id.rvContacts);
  LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
  recyclerView.setLayoutManager(linearLayoutManager);
  // Add the scroll listener
  rvItems.addOnScrollListener(new EndlessRecyclerViewScrollListener(linearLayoutManager) {
   @Override
   public void onLoadMore(int page, int totalItemsCount) {
    // Triggered only when new data needs to be appended to the list
    // Add whatever code is needed to append new items to the bottom of the list
    customLoadMoreDataFromApi(page);
   }
  });
 }

 // Append more data into the adapter
 // This method probably sends out a network request and appends new data items to your adapter.
 public void customLoadMoreDataFromApi(int page) {
  // Send an API request to retrieve appropriate data using the offset value as a parameter.
  // --> Deserialize API response and then construct new objects to append to the adapter
  // --> Notify the adapter of the changes
 }
}

EndlessRecyclerView

public abstract class EndlessRecyclerViewScrollListener extends RecyclerView.OnScrollListener {
 // The minimum amount of items to have below your current scroll position
 // before loading more.
 private int visibleThreshold = 5;
 // The current offset index of data you have loaded
 private int currentPage = 0;
 // The total number of items in the dataset after the last load
 private int previousTotalItemCount = 0;
 // True if we are still waiting for the last set of data to load.
 private boolean loading = true;
 // Sets the starting page index
 private int startingPageIndex = 0;

 RecyclerView.LayoutManager mLayoutManager;

 public EndlessRecyclerViewScrollListener(LinearLayoutManager layoutManager) {
  this.mLayoutManager = layoutManager;
 }

 public EndlessRecyclerViewScrollListener(GridLayoutManager layoutManager) {
  this.mLayoutManager = layoutManager;
  visibleThreshold = visibleThreshold * layoutManager.getSpanCount();
 }

 public EndlessRecyclerViewScrollListener(StaggeredGridLayoutManager layoutManager) {
  this.mLayoutManager = layoutManager;
  visibleThreshold = visibleThreshold * layoutManager.getSpanCount();
 }

 public int getLastVisibleItem(int[] lastVisibleItemPositions) {
  int maxSize = 0;
  for (int i = 0; i < lastVisibleItemPositions.length; i++) {
   if (i == 0) {
    maxSize = lastVisibleItemPositions[i];
   }
   else if (lastVisibleItemPositions[i] > maxSize) {
    maxSize = lastVisibleItemPositions[i];
   }
  }
  return maxSize;
 }

 // This happens many times a second during a scroll, so be wary of the code you place here.
 // We are given a few useful parameters to help us work out if we need to load some more data,
 // but first we check if we are waiting for the previous load to finish.
 @Override
 public void onScrolled(RecyclerView view, int dx, int dy) {
  int lastVisibleItemPosition = 0;
  int totalItemCount = mLayoutManager.getItemCount();

  if (mLayoutManager instanceof StaggeredGridLayoutManager) {
   int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(null);
   // get maximum element within the list
   lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions);
  } else if (mLayoutManager instanceof LinearLayoutManager) {
   lastVisibleItemPosition = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition();
  } else if (mLayoutManager instanceof GridLayoutManager) {
   lastVisibleItemPosition = ((GridLayoutManager) mLayoutManager).findLastVisibleItemPosition();
  }

  // If the total item count is zero and the previous isn't, assume the
  // list is invalidated and should be reset back to initial state
  if (totalItemCount < previousTotalItemCount) {
   this.currentPage = this.startingPageIndex;
   this.previousTotalItemCount = totalItemCount;
   if (totalItemCount == 0) {
    this.loading = true;
   }
  }
  // If it's still loading, we check to see if the dataset count has
  // changed, if so we conclude it has finished loading and update the current page
  // number and total item count.
  if (loading && (totalItemCount > previousTotalItemCount)) {
   loading = false;
   previousTotalItemCount = totalItemCount;
  }

  // If it isn't currently loading, we check to see if we have breached
  // the visibleThreshold and need to reload more data.
  // If we do need to reload some more data, we execute onLoadMore to fetch the data.
  // threshold should reflect how many total columns there are too
  if (!loading && (lastVisibleItemPosition + visibleThreshold) > totalItemCount) {
   currentPage++;
   onLoadMore(currentPage, totalItemCount);
   loading = true;
  }
 }

 // Defines the process for actually loading more data based on page
 public abstract void onLoadMore(int page, int totalItemsCount);

}

注意问题:
 1.对于ListView,确定将绑定监听器的步骤放在onCreate()的方法中
 2.为可加可靠的进行分页,需要确定在向列表中添加新数据的时候先清理适配器中的数据
对于RecyclerView来说在通知适配器时推荐更细致的更新。
 3.对于RecyclerView来说确保在清除列表中的数据的时候迅速的通知适配器内容更新了,以便于可以触发新的onScroll事件,重置自己

展示进度条

为了在底部展示进度条证明ListView正在加载。我们可以在Adapter中进行设置,我们可以定义两类,可以是进度条类型或者是文本表明达到了最底行,参考:http://guides.codepath.com/android/Endless-Scrolling-with-AdapterViews-and-RecyclerView

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

(0)

相关推荐

  • Android使用RecyclerView实现水平滚动控件

    前言 相信大家都知道Android滚动控件的实现方式有很多, 使用RecyclerView也比较简单. 做了一个简单的年龄滚动控件, 让我们来看看RecyclerView的使用方式, 主要有以下几点: (1) 对齐控件中心位置. (2) 计算滚动距离. (3) 高亮中心视图. (4) 实时显示中心数据. (5) 停止时自动对齐. (6) 滚动时, 设置按钮状态开关. 效果 1. 框架 主要关注RecyclerView部分逻辑. /** * 初始化年龄滑动条 */ private void ini

  • Android RecylerView入门教程

    今年Google I/0大会,Google开放了两个全新的视图:RecyclerView和CardView.这篇文章会提供关于RecylerView的简介. RecylerView作为support-library发布出来,这对开发者来说绝对是个好消息.因为可以在更低的Android版本上使用这个新视图.下面我们看如何获取RecylerView.首先打开Android SDK Manager,然后更新Extras->Android Support Library即可. 然后在本地../sdk/e

  • Android中RecyclerView实现分页滚动的方法详解

    一.需求分析 最近公司项目要实现一个需求要满足以下功能: 1)显示一个 list 列表, item 数量不固定. 2)实现翻页功能,一次翻一页. 3)实现翻至某一页功能. 下面介绍通过 RecyclerView 实现该需求的实现过程(效果图如下). 二.功能实现 2.1 OnTouchListener 记录当前开始滑动位置 要实现翻页滑动首先我们要确定是向前翻页还是向后翻页,这里通过记录开始翻页前当前的位置和滑动后的位置比较即可得知,下面选择手指触摸按下时滑动的位置为当前开始滑动位置: //当前

  • 功能强大的Android滚动控件RecyclerView

    RecyclerView的使用比ListView的使用是比较复杂的,ListView的使用是五个步骤,而我们的RecyclerView的使用有7个步骤,分别为: 1.在当前项目的build.gradle中的dependencies闭包中加入compile 'com.android.support.recyclerview-v7:xx.x.x'(x是当前最新版本) 2.布局加入RecyclerView控件以及创建子项布局和适配器类. 3.创建适配器 4.定义数据源 5.通过findViewById

  • Android使用Recyclerview实现图片水平自动循环滚动效果

    简介: 本篇博客主要介绍的是如何使用RecyclerView实现图片水平方向自动循环(跑马灯效果) 效果图:  思路: 1.准备m张图片 1.使用Recyclerview实现,返回无数个(实际Interge.MAXVALUE)item,第n个item显示第n%m张图片 3.使用recyclerview.scrollBy  每个一段时间水平滚动一段距离 4.通过layoutManager.findFirstVisibleItemPosition()获取当前显示的第一个View是第几个item,上面

  • Android_RecyclerView实现上下滚动广告条实例(带图片)

    前言 公司新项目首页有个类似京东/淘宝滚动广告条,查了一下大概都是两种实现方式,一是textview,如果只有文字的话是可行的,但我们这个上面还有个小图片,所以pass:二是两个viewGroup,使用动画交替滚动,可以实现,就是显得很麻烦,于是偷懒的我就想着用recyclerView来解决这个小问题! 思路 这个滚动广告条高度通常是固定的,用一个固定高度的viewGroup来包裹一个recyclerView,recylerView的item布局设置一个minHeight为viewGroup的高

  • Android RecyclerView滚动定位

    概述 RecyclerView在安卓开发中非常实用,而且简单易用,但是在实际开发中一直有一个问题困扰着我,就是定位问题,实际的项目中总是会遇到这样的需求:检索RecyclerView的某一项(各个项的高度不确定),然后定位这一项,将它显示在顶部.用RecyclerView的默认移动的方法并不能实现这一点(个人感觉官方可能出于性能考虑才不实现这一点).这篇博客就讲解下我个人是如何实现这个需求的. Demo演示 敲代码前的思考 RecyclerView提供的用于控制移动的方法有2个 - scroll

  • Android代码实现AdapterViews和RecyclerView无限滚动

    应用的一个共同的特点就是当用户欢动时自动加载更多的内容,这是通过用户滑动触发一定的阈值时发送数据请求实现的. 相同的是:信息实现滑动的效果需要定义在列表中最后一个可见项,和某些类型的阈值以便于开始在最后一项到达之前开始抓取数据,实现无限的滚动. 实现无限滚动的现象的重要之处就在于在用户滑动到最低端之前就行数据的获取,所以需要加上一个阈值来帮助实现获取数据的预期. 使用ListView和GridView实现 每个AdapterView 例如ListView 和GridView 当用户开始进行滚动操

  • Android简单实现无限滚动自动滚动的ViewPager

    经常我们会在应用中看到一个可以自动滚动,并且无限滚动的一个ViewPager,百度谷歌上面也有很多关于这方面的教程,但是感觉都略显麻烦,而且封装的都不是很彻底.所以试着封装一个比较好用的ViewPager 效果如下: 简单的说一下实现思路,要实现无限滚动的话就要在PagerAdapter上面做一些手脚,在PagerAdapter的getCount的函数的返回值设置成Integer.MXA_VALUE就可以实现向右无限滚动,但是要实现向左无限滚动呢?就是一开始的时候setCurrentItem的时

  • vue使用mint-ui实现下拉刷新和无限滚动的示例代码

    在开发web-app中,总会遇到v-for出来的li会有很多,当数据达几百上千条的时候,一起加载出来会造成用户体验很差的效果. 这时候我们可以使用无限滚动和下拉刷新来实现控制显示的数量,当刷新到底部的边界的时候会触发无限滚动的事件,再次加载一定数量的条目. 还是拿在项目中的功能来举栗子介绍. 有个列表,几千条数据,做分页查询,限制每次显示查询20条,每次拉到最后20条边缘的时候,触发无限滚动,这时候会出现加载图标,继续加载后续20条数据,加载到最后的时候会提示数据"加载完毕". 项目的

  • 原生JS利用transform实现banner的无限滚动示例代码

    功能 默认情况无限循环向右移动 点击数字切换到对应图片 点击左右切换可切换图片 原理 首先说下原理. 在布局上所有的图片都是重叠的,即只要保证Y方向对齐即可,当前可见的图z-index层级最高. 每隔3s中更换一张图片,使用setTimeout定时. 使用gIndex记录当前可视区域的展示的是哪张图片下标,每次更换,计算下一张图片的下标. 通过requestAnimationFrame实现一次图片切换的动画. 这种方法也可以做到整个页面始终只有2个img标签,而不必把所有的img节点全部创建出来

  • Android App开发中使用RecyclerView实现Gallery画廊的实例

    什么是RecyclerView         RecyclerView是Android 5.0 materials design中的组件之一,相应的还有CardView.Palette等.看名字我们就能看出一点端倪,没错,它主要的特点就是复用.我们知道,Listview中的Adapter中可以实现ViewHolder的复用.RecyclerView提供了一个耦合度更低的方式来复用ViewHolder,并且可以轻松的实现ListView.GridView以及瀑布流的效果. RecyclerVie

  • Android App开发中使用RecyclerView替代ListView的实践

    RecyclerView是Android 5.0的新特性,可以直接代替ListView与GridView,并且能够实现瀑布流的布局,感觉RecyclerView使用的好处就是它不关心布局,只关心资源的回收与复用,正因为如此,RecyclerView中将ViewHolder进行了单独的编写,这也正是google所不断提倡的,另外,RecyclerView能够更简单的实现布局的转换. 新的视图类RecyclerView,它被用来代替ListView以及GridView,提供更为高效的回收复用机制,同

  • iOS利用UIScrollView实现无限滚动效果

    前言 众所周知UIScrollView 的无限滚动主要应用在图片轮播器.欢迎界面等场景.它的原理是在要显示的图片前后各加一张图片即在第一张图片之前放最后一张图片,在最后一张图片之后放第一张图片,然后在滚动到边缘的时候,巧妙的过渡一下就可以"瞒天过海","以假乱真"的造成无限滚动的假象.网络上有很多只用三张或两张图片实现的方法,效率比这个方法高,但实现起来稍微麻烦一点,有兴趣的可以去深入研究. 实现步骤 1.根据需求准备几张图片,在网上找了5张图片,分别命名为 img

  • IOS开发之UIScrollView实现图片轮播器的无限滚动

    IOS开发之UIScrollView实现图片轮播器的无限滚动 简介 在现在的一些App中常常见到图片轮播器,一般用于展示广告.新闻等数据,在iOS内并没有现成的控件直接实现这种功能,但是通过UIScrollView的允许分页设置,可以实现滚动轮播的功能. 轮播原理 UIScrollView对象有pagingEnable成员,如果设置为YES,那么每一个scrollView尺寸这么大的区域就会被当作一页,在滚动时会根据滚动的比例自动计算应该切换到哪一页. 无限滚动原理 要实现无限滚动,需要额外的两

  • iOScollectionView广告无限滚动实例(Swift实现)

    今天公司里的实习生跑过来问我一般App上广告的无限滚动是怎么实现的,刚好很久没写博客了,就决定写下了,尽量帮助那些处于刚学iOS的程序猿. 做一个小demo,大概实现效果如下图所示: 基本实现思路: 1. 在你需要放置无限滚动展示数据的地方把他的数据,在原本的基础上把你要展示的数据扩大三倍.(当然扩大两倍也是可以的,三倍的话,比较好演示) // MARK: - 设置数据源 func collectionView(_ collectionView: UICollectionView, number

  • 使用Swift实现iOScollectionView广告无限滚动效果(DEMO)

    今天公司里的实习生跑过来问我一般App上广告的无限滚动是怎么实现的,刚好很久没写博客了,就决定写下了,尽量帮助那些处于刚学iOS的程序猿. 做一个小demo,大概实现效果如下图所示: 基本实现思路: 1. 在你需要放置无限滚动展示数据的地方把他的数据,在原本的基础上把你要展示的数据扩大三倍.(当然扩大两倍也是可以的,三倍的话,比较好演示) // MARK: - 设置数据源 func collectionView(_ collectionView: UICollectionView, number

随机推荐