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 ...
随机推荐
- Java8新特性_接口中的默认方法
默认方法由来猜想 1. Collection接口.Collections公共类. 同是操作集合,为啥要搞俩?没必要.在接口中搞一些默认实现,一个接口即搞定了. 2. Java8支持Lambda表达式 ...
- webpack学习笔记——打包js
1.新建一个入口js文件,如entry.js,代码如下: document.write("It works.") 2.然后编译 entry.js 并打包到 bundle.js(会自 ...
- oracle.sql.TIMESTAMP转为java.sql.TIMESTAMP的方法
/** * @reference oracle.sql.Datum.timestampValue(); * @return */ private Timestamp getOracleTimestam ...
- 代码管理工具Git的安装及使用
一:Git是什么? Git是目前世界上最先进的分布式版本控制系统. 二:SVN与Git的最主要的区别? SVN是集中式版本控制系统,版本库是集中放在中央服务器的,而干活的时候,用的都是自己的电脑,所以 ...
- Vue.js 技术揭秘(学习) 深入响应式原理 nextTick外传
microTask mutationObserve. promise.then macroTask setImmediate. messageChannnel.setTimeout.postMess ...
- border-radius图解
自己看了理解的border-radius: 设置参数: 100*100的正方形,第一个:border-top-left-radius:100px 100px,即圆的半径为100px.圆弧与上和左bor ...
- Java HashMap工作原理及实现[转]
原文:http://yikun.github.io/2015/04/01/Java-HashMap%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86%E5%8F%8A%E5%AE ...
- Debian 9 美化界面
Debian 桌面美化 安装 gnome-tweak-tool aptitude install gnome-tweak-tool 登陆gnome-look下载主题包 gnome-look上有很多主题 ...
- P2050 [NOI2012]美食节
题目地址:P2050 [NOI2012]美食节 先来讲一下P2053 [SCOI2007]修车(如果会做请跳过) 同一时刻有 \(N\) 位车主带着他们的爱车来到了汽车维修中心.维修中心共有 \(M\ ...
- JavaWeb - Servlet教程
http://www.runoob.com/servlet/servlet-tutorial.html


