个人主页
演示Demo下载


本文重点介绍了SwipeRefreshLayout的使用和自定View继承SwipeRefreshLayout添加上拉加载更多的功能。

  • 介绍之前,先来看一下SwipeRefreshLayout实现的下拉刷新效果图。从图中可以看到,下拉到了一定的高度才会进行刷新,高度不够就会回收上去,正在刷新过程中,继续下拉没反应,说明刷新时屏蔽掉了下拉事件。

     
    上拉刷新效果图

一、SwipeRefreshLayout简单介绍

  • 先看以下官方文档,已有了很详细的描述了。

     
    官方文档说明
  • 这里我再大概解释一下:

    • 在竖直滑动时想要刷新页面可以用SwipeRefreshLayout来实现。它通过设置OnRefreshListener来监听界面的滑动从而实现刷新。也可以通过一些方法来设置SwipeRefreshLayout是否可以刷新。如:setRefreshing(true),展开刷新动画。
      setRefreshing(false),取消刷新动画。setEnable(true)下拉刷新将不可用。

    • 使用这个布局要想达到刷新的目的,需要在这个布局里包裹可以滑动的子控件,如ListView等,并且只能有一个子控件。

  • 介绍总结:使用SwipeRefreshLayout可以实现下拉刷新,前提是布局里需要包裹一个可以滑动的子控件,然后在代码里设置OnRefreshListener设置监听,最后在监听里设置刷新时的数据获取就可以了。由于是新出来的东西,所以要想使用,先把support library的版本升级到19.1或更新。

二、SwipeRefreshLayout主要方法介绍

翻看官方的文档,可以看到方法有很多,这里只介绍五个经常用到的方法。

  • isRefreshing()

    • 判断当前的状态是否是刷新状态。
  • setColorSchemeResources(int... colorResIds)

    • 设置下拉进度条的颜色主题,参数为可变参数,并且是资源id,可以设置多种不同的颜色,每转一圈就显示一种颜色。
  • setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener)

    • 设置监听,需要重写onRefresh()方法,顶部下拉时会调用这个方法,在里面实现请求数据的逻辑,设置下拉进度条消失等等。
  • setProgressBackgroundColorSchemeResource(int colorRes)

    • 设置下拉进度条的背景颜色,默认白色。
  • setRefreshing(boolean refreshing)

    • 设置刷新状态,true表示正在刷新,false表示取消刷新。

三、SwipeRefreshLayout的基本使用

  • 介绍了SwipeRefreshLayout,主要的方法也讲了,接下来就是实战,其实使用起来非常的简单。

3.1 设置布局

  • 官方文档已经说明,SwipeRefreshLayout只能有一个孩子,当然我们不般也不会往里面放其他的布局。我们只需要在容器里包裹一个ListView就好了。

   <ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent"/> </android.support.v4.widget.SwipeRefreshLayout>
-->

3.2 在代码中使用

  • 在该布局文件对应的Activity或其他类中获取布局id,先设置ListView显示的适配器,然后再设置SwipeRefreshLayout。
    // 不能在onCreate中设置,这个表示当前是刷新状态,如果一进来就是刷新状态,SwipeRefreshLayout会屏蔽掉下拉事件
    //swipeRefreshLayout.setRefreshing(true);

// 设置颜色属性的时候一定要注意是引用了资源文件还是直接设置16进制的颜色,因为都是int值容易搞混
// 设置下拉进度的背景颜色,默认就是白色的
swipeRefreshView.setProgressBackgroundColorSchemeResource(android.R.color.white);
// 设置下拉进度的主题颜色
swipeRefreshView.setColorSchemeResources(R.color.colorAccent, R.color.colorPrimary, R.color.colorPrimaryDark); // 下拉时触发SwipeRefreshLayout的下拉动画,动画完毕之后就会回调这个方法
swipeRefreshView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() { // 开始刷新,设置当前为刷新状态
//swipeRefreshLayout.setRefreshing(true); // 这里是主线程
// 一些比较耗时的操作,比如联网获取数据,需要放到子线程去执行
// TODO 获取数据
final Random random = new Random();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mList.add(, "我是天才" + random.nextInt() + "号");
mAdapter.notifyDataSetChanged(); Toast.makeText(MainActivity.this, "刷新了一条数据", Toast.LENGTH_SHORT).show(); // 加载完数据设置为不刷新状态,将下拉进度收起来
swipeRefreshView.setRefreshing(false);
}
}, ); // System.out.println(Thread.currentThread().getName()); // 这个不能写在外边,不然会直接收起来
//swipeRefreshLayout.setRefreshing(false);
}
});
  • 经过以上两步简单的设置就能使用SwipeRefreshLayout了。

四、自定义View继承SwipeRefreshLayout,添加上拉加载更多功能

由于谷歌并没有提供上拉加载更多的布局,所以我们只能自己去定义布局实现这个功能。

这里通过自定义View继承SwipeRefreshLayout容器,然后添加上拉加载更多的功能。

  • 先来看一下上拉加载更多的效果图

     
    上拉加载更多效果图

4.1 定义View继承SwipeRefreshLayout,添加上拉加载功能

代码中的注释比较详细,这里就不一一解释了,说一下大概的实现思路,主要分为四步。

4.1.1 获取子控件ListView

  • 在布局使用中,这里和SwipeRefreshLayout一样,ListView是SwipeRefreshView的子控件,所以需要在onLayout()方法中获取子控件ListView。
    // 获取ListView,设置ListView的布局位置
    if (mListView == null) {
    // 判断容器有多少个孩子
    if (getChildCount() > 0) {
    // 判断第一个孩子是不是ListView
    if (getChildAt(0) instanceof ListView) {
    // 创建ListView对象
    mListView = (ListView) getChildAt(0);

     // 设置ListView的滑动监听
setListViewOnScroll();
}
}
}

4.1.2 对ListView设置滑动监听

  • 监听ListView的滑动事件,当滑动到底部,并且当前可见页的最后一个条目等于adapter的getCount数目-1,就满足加载数据的条件。
    /**
    * 设置ListView的滑动监听
    */
    private void setListViewOnScroll() {

mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// 移动过程中判断时候能下拉加载更多
if (canLoadMore()) {
// 加载数据
loadData();
}
} @Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { }
});
}

4.1.3 处理SwipeRefreshView容器的分发事件

  • 由于ListView是SwipeRefreshView的子控件,所以这里要进行事件的分发处理,判断用户的滑动距离是否满足条件。
    /**
    * 在分发事件的时候处理子控件的触摸事件
    *
    * @param ev
    * @return
    */
    private float mDownY, mUpY;
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {

switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
// 移动的起点
mDownY = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
// 移动过程中判断时候能下拉加载更多
if (canLoadMore()) {
// 加载数据
loadData();
} break;
case MotionEvent.ACTION_UP:
// 移动的终点
mUpY = getY();
break;
}
return super.dispatchTouchEvent(ev);
}

4.1.4 判断条件,满足就用回调去加载数据

  • 当满足了需要判断的所有的条件之后,就可以去调用加载数据的方法,这里提供一个设置上拉布局显示和隐藏的方法,通过传入当前的状态,是true就显示加载,是false就隐藏。
    /**
    * 判断是否满足加载更多条件
    *
    * @return
    */
    private boolean canLoadMore() {
    // 1. 是上拉状态
    boolean condition1 = (mDownY - mUpY) >= mScaledTouchSlop;
    if (condition1) {
    System.out.println("是上拉状态");
    }

// 2. 当前页面可见的item是最后一个条目
boolean condition2 = false;
if (mListView != null && mListView.getAdapter() != null) {
condition2 = mListView.getLastVisiblePosition() == (mListView.getAdapter().getCount() - );
} if (condition2) {
System.out.println("是最后一个条目");
}
// 3. 正在加载状态
boolean condition3 = !isLoading;
if (condition3) {
System.out.println("不是正在加载状态");
}
return condition1 && condition2 && condition3;
} /**
* 处理加载数据的逻辑
*/
private void loadData() {
System.out.println("加载数据...");
if (mOnLoadListener != null) {
// 设置加载状态,让布局显示出来
setLoading(true);
mOnLoadListener.onLoad();
} } /**
* 设置加载状态,是否加载传入boolean值进行判断
*
* @param loading
*/
public void setLoading(boolean loading) {
// 修改当前的状态
isLoading = loading;
if (isLoading) {
// 显示布局
mListView.addFooterView(mFooterView);
} else {
// 隐藏布局
mListView.removeFooterView(mFooterView); // 重置滑动的坐标
mDownY = ;
mUpY = ;
}
}

4.2 使用自定义View

4.2.1. 书写布局

  • 因为是继承自SwipeRefreshLayout,所以SwipeRefreshView也只能有一个孩子

    <!--自定义View实现SwipeRefreshLayout,添加上拉加载更多的功能-->
    <com.pinger.swiperefreshdemo.view.SwipeRefreshView
    android:id="@+id/srl"
    android:layout_width="match_parent"
    android:layout_height="match_parent"> <ListView
    android:id="@+id/lv"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/> </com.pinger.swiperefreshdemo.view.SwipeRefreshView>

    4.2.2. 在代码中使用

    • 在代码中使用更加的简单,只需要设置监听重写onLoad()方法,在里面加载数据,加载完数据然后设置为不加载状态就可以了。

      // 设置下拉加载更多
      swipeRefreshView.setOnLoadListener(new SwipeRefreshView.OnLoadListener() {
      @Override
      public void onLoad() {
      new Handler().postDelayed(new Runnable() {
      @Override
      public void run() { // 添加数据
      for (int i = ; i < ; i++) {
      mList.add("我是天才" + i+ "号");
      // 这里要放在里面刷新,放在外面会导致刷新的进度条卡住
      mAdapter.notifyDataSetChanged();
      } Toast.makeText(MainActivity.this, "加载了" + + "条数据", Toast.LENGTH_SHORT).show(); // 加载完数据设置为不加载状态,将加载进度收起来
      swipeRefreshView.setLoading(false);
      }
      }, );
      }
      });

个人主页
演示Demo下载

以上纯属于个人平时工作和学习的一些总结分享,如果有什么错误欢迎随时指出,大家可以讨论一起进步。

SwipeRefreshLayout详解和自定义上拉加载更多的更多相关文章

  1. google官方的下拉刷新+自定义上拉加载更多

    转载请标注转载:http://blog.csdn.net/oqihaogongyuan/article/details/50949118 google官方的下拉刷新+自定义上拉加载更多 现在很多app ...

  2. 实现上拉加载更多的SwipeRefreshLayout

    转载请标明出处: http://blog.csdn.net/developer_jiangqq/article/details/49992269 本文出自:[江清清的博客] (一).前言: [好消息] ...

  3. Android中自定义ListView实现上拉加载更多和下拉刷新

    ListView是Android中一个功能强大而且很常用的控件,在很多App中都有ListView的下拉刷新数据和上拉加载更多这个功能.这里我就简单记录一下实现过程. 实现这个功能的方法不止一个,Gi ...

  4. react-native-page-listview使用方法(自定义FlatList/ListView下拉刷新,上拉加载更多,方便的实现分页)

    react-native-page-listview 对ListView/FlatList的封装,可以很方便的分页加载网络数据,还支持自定义下拉刷新View和上拉加载更多的View.兼容高版本Flat ...

  5. 自定义ListView下拉刷新上拉加载更多

    自定义ListView下拉刷新上拉加载更多 自定义RecyclerView下拉刷新上拉加载更多 Listview现在用的很少了,基本都是使用Recycleview,但是不得不说Listview具有划时 ...

  6. react-native 自定义 下拉刷新 / 上拉加载更多 组件

    1.封装 Scroller 组件 /** * 下拉刷新/上拉加载更多 组件(Scroller) */ import React, {Component} from 'react'; import { ...

  7. RecyclerView实例-实现可下拉刷新上拉加载更多并可切换线性流和瀑布流模式(1)

    摘要 最近项目有个列表页需要实现线性列表和瀑布流展示的切换,首先我想到的就是上 [RecyclerView],他本身已经很好的提供了三种布局方式,只是简单做个切换应该是很简单的事情,如果要用Recyc ...

  8. Android 开发 上拉加载更多功能实现

    实现思维 开始之前先废话几句,Android系统没有提供上拉加载的控件,只提供了下拉刷新的SwipeRefreshLayout控件.这个控件我们就不废话,无法实现上拉刷新的功能.现在我们说说上拉加载更 ...

  9. RecyclerView下拉刷新上拉加载更多

    现在Android里都建议用RecyclerView代替ListView和GridView,所以下拉刷新和上拉加载更多也需要实现.下拉刷新可以用SwipeRefreshLayout 包裹Recycle ...

随机推荐

  1. QWidget扩充父子关系

    childAt(x, y)      获取在指定坐标处的子控件 parentWidget()      获取指定控件的父控件 s=label.parentWidget()     #返回label的父 ...

  2. 数据库设计理论与实践·<四>数据库基本术语及其概念

    一.关系模型 关系模型是最重要的一种数据模型.关系数据库模型系统采用关系模型作为数据的组织方式. 关系模型的数据结构: 关系:一张表 元组:一行记录. 属性:一列 [码(键,key)]:表中的某个属性 ...

  3. JQ中的 offsetTop 和 offset().top 的区别

    话不多说先上图: offset()的top是指元素与document的上边的距离,而不是浏览器当前窗体的上边缘,如图 document高度超过window,浏览器出现滚动条,滚动滚动条,提交按钮的of ...

  4. angular vue react web前端三大主流框架的对比

    首先,我们先了解什么是MVX框架模式? MVX框架模式:MVC+MVP+MVVM 1.MVC:Model(模型)+View(视图)+controller(控制器),主要是基于分层的目的,让彼此的职责分 ...

  5. Linux查看系统的基本信息

    uname -r :显示操作系统的发行版号 uname -a:显示系统名.节点名称.操作系统的发行版号.操作系统版本.运行系统的机器 ID 号. # Ubuntu系统 ubuntu@VM-28-69- ...

  6. 小程序view排版

    <view class="bc"> <view> <text bc_text>demo</text> </view> & ...

  7. Windows 7 SP1无人值守自动应答文件制作

    使用U盘安装Windows系统时,很多人都会使用UltraISO工具来制作U盘启动盘,然后插入到电脑中加以安装.系统的安装过程中,需要一步一步手动选择或者输入配置,Windows是支持无人值守自动应答 ...

  8. 音乐app各部分笔记(一)

    7-11 播放器播放时间获取和更新 1.audio 有一个 ontimeupdate事件 播放过程中 随时触发 vue里面就是  @timeupdate   事件中有默认参数 e  通过e.targe ...

  9. 工具方法 .js

    1. 获取url问号后面,name的值 /** * *?id=123&a=b * @return object */export function urlParse(){ let url = ...

  10. POJ 3253 Fence Repair (贪心)

    题意:将一块木板切成N块,长度分别为:a1,a2,……an,每次切割木板的开销为当前木板的长度.求出按照要求将木板切割完毕后的最小开销. 思路:比较奇特的贪心 每次切割都会将当前木板一分为二,可以按切 ...