SwipeRefreshLayout详解和自定义上拉加载更多
本文重点介绍了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);
}
}, );
}
});
以上纯属于个人平时工作和学习的一些总结分享,如果有什么错误欢迎随时指出,大家可以讨论一起进步。
SwipeRefreshLayout详解和自定义上拉加载更多的更多相关文章
- google官方的下拉刷新+自定义上拉加载更多
转载请标注转载:http://blog.csdn.net/oqihaogongyuan/article/details/50949118 google官方的下拉刷新+自定义上拉加载更多 现在很多app ...
- 实现上拉加载更多的SwipeRefreshLayout
转载请标明出处: http://blog.csdn.net/developer_jiangqq/article/details/49992269 本文出自:[江清清的博客] (一).前言: [好消息] ...
- Android中自定义ListView实现上拉加载更多和下拉刷新
ListView是Android中一个功能强大而且很常用的控件,在很多App中都有ListView的下拉刷新数据和上拉加载更多这个功能.这里我就简单记录一下实现过程. 实现这个功能的方法不止一个,Gi ...
- react-native-page-listview使用方法(自定义FlatList/ListView下拉刷新,上拉加载更多,方便的实现分页)
react-native-page-listview 对ListView/FlatList的封装,可以很方便的分页加载网络数据,还支持自定义下拉刷新View和上拉加载更多的View.兼容高版本Flat ...
- 自定义ListView下拉刷新上拉加载更多
自定义ListView下拉刷新上拉加载更多 自定义RecyclerView下拉刷新上拉加载更多 Listview现在用的很少了,基本都是使用Recycleview,但是不得不说Listview具有划时 ...
- react-native 自定义 下拉刷新 / 上拉加载更多 组件
1.封装 Scroller 组件 /** * 下拉刷新/上拉加载更多 组件(Scroller) */ import React, {Component} from 'react'; import { ...
- RecyclerView实例-实现可下拉刷新上拉加载更多并可切换线性流和瀑布流模式(1)
摘要 最近项目有个列表页需要实现线性列表和瀑布流展示的切换,首先我想到的就是上 [RecyclerView],他本身已经很好的提供了三种布局方式,只是简单做个切换应该是很简单的事情,如果要用Recyc ...
- Android 开发 上拉加载更多功能实现
实现思维 开始之前先废话几句,Android系统没有提供上拉加载的控件,只提供了下拉刷新的SwipeRefreshLayout控件.这个控件我们就不废话,无法实现上拉刷新的功能.现在我们说说上拉加载更 ...
- RecyclerView下拉刷新上拉加载更多
现在Android里都建议用RecyclerView代替ListView和GridView,所以下拉刷新和上拉加载更多也需要实现.下拉刷新可以用SwipeRefreshLayout 包裹Recycle ...
随机推荐
- IDEA导入JUnit4
Step 1. IDEA最上面一栏的菜单栏中,选File->Project Structure(从上往下第11个),弹出窗口左边有一个列表,选Module. Step 2. 右侧有一个带3个标签 ...
- windows下通过压缩包安装MySQL
一.下载压缩包 二.解压缩后存放在该路径下 三.配置环境变量 将D:\Program Files\mysql-8.0.11-winx64\bin添加到用户PATH变量或系统PATH变量中 ...
- HTML 实例学习(基础)
1.HTML <html> 标签 注意:对于中文网页需要使用 <meta charset="utf-8"> 声明编码,否则会出现乱码.有些浏览器会设置 GB ...
- 三十七、Linux 线程——线程清理和控制函数、进程和线程启动方式比较、线程的状态转换
37.1 线程清理和控制函数 #include <pthread.h> void pthread_cleanup_push(void (* rtn)(void *), void *arg) ...
- 复习java web之jsp入门_El表达式_JSTL标签库
JSP 技术掌握:JSP语法 + EL + JSTL 为什么sun推出 JSP技术 ? Servlet 生成网页比较复杂,本身不支持HTML语法,html代码需要通过response输出流输出,JSP ...
- Chrome实用技巧集锦
1. 截取整个网页内容: 步骤:(F12 或 Ctrl Shift I 进入开发者模式) ——> Ctrl Shift P 弹出输入框 ——> 输入框中输入:Captrue ful ...
- luogu P3312 [SDOI2014]数表
传送门 我们看要求的东西\[\sum_{i=1}^{n}\sum_{j=1}^{m}[\sigma(gcd(i,j))\le a]\sigma(gcd(i,j))\] 然而\(\le a\)比较烦,可 ...
- 检查CentOS7定时任务是否启用并执行过
1 监控cron状态 service crontab status #如果没有开启执行 service crontab start 正常开启的状态 2 检查执行日志,过滤自己配置的定时任务脚本关键字 ...
- python函数解释
实现某个功能的一些代码提高代码的复用性函数必须被调用才会执行函数里面定义的变量都叫局部变量,只要一出了函数就不能用了函数里面如果调用时需要拿到结果但是最后没写return(不必须写,如读取文件时就需要 ...
- Mybatis(一)入门介绍
一.MyBatis的发展 MyBatis 是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation迁移到google code, 并且改名M ...


