最近在负责了两三个项目,然后很多地方展示列表数据都用到了下拉刷新或者上拉加载或者两者兼有。
- 我用的是一个开源框架:Ultra Pull to Refresh with Load More
- 这是一个GitHub上的开源项目,本分支是对原有的Ultra Pull To Refresh进行了修改,使得其支持了上拉加载更多。
下面来说一下在项目中的使用吧!
- 首先你需要先在你的开发工具中引用这个第三方库,在你的gradle中添加:
compile ‘in.srain.cube:ptr-load-more:1.0.6’
然后等待studio同步一下配置即可以在xml文件中使用该控件了。
- 该框架你需要在xml中引用控件如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.demo.ultrapulltorefreshdemo.MainActivity">
<in.srain.cube.views.ptr.PtrFrameLayout
android:id="@+id/ptr_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<!-- 这里可以是任何view,是不是很棒 -->
<ImageView
android:id="@+id/iv_demo"
android:src="@mipmap/demo"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</in.srain.cube.views.ptr.PtrFrameLayout>
</RelativeLayout>
上面的 in.srain.cube.views.ptr.PtrFrameLayout 就是需要在xml布局文件中使用的view,这是一定要添加的,所有的操作都是根据这个view来实现的。
然后里面可以添加任何控件,你想操作textview、imageview、listview或者其他任何view,你只要添加到这个view里面即可。我这里用的是一个imageview。
然后你需要给这个view加一些必要的属性,用来控制下拉时的阻尼系数,控制刷新回弹时间等等。
- 这些属性的设置有两种配置方法
一种是在xml中配置,示例如下:
<in.srain.cube.views.ptr.PtrFrameLayout
android:id="@+id/store_house_ptr_frame"
xmlns:cube_ptr="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
cube_ptr:ptr_resistance="1.7"
cube_ptr:ptr_ratio_of_header_height_to_refresh="1.2"
cube_ptr:ptr_duration_to_close="300"
cube_ptr:ptr_duration_to_close_header="2000"
cube_ptr:ptr_keep_header_when_refresh="true"
cube_ptr:ptr_pull_to_fresh="false" >
<LinearLayout
android:id="@+id/store_house_ptr_image_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/cube_mints_333333"
android:clickable="true"
android:padding="10dp">
<in.srain.cube.image.CubeImageView
android:id="@+id/store_house_ptr_image"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</in.srain.cube.views.ptr.PtrFrameLayout>
第二种是在代码中配置,示例如下:
// 头部阻尼系数
ptr_frame.setResistanceHeader(1.7f);
// 底部阻尼系数
ptr_frame.setResistanceFooter(1.7f);
// 默认1.2f,移动达到头部高度1.2倍时触发刷新操作
ptr_frame.setRatioOfHeaderHeightToRefresh(1.2f);
// 头部回弹时间
ptr_frame.setDurationToCloseHeader(1000);
// 底部回弹时间
ptr_frame.setDurationToCloseFooter(1000);
// 释放刷新
ptr_frame.setPullToRefresh(false);
// 释放时恢复到刷新状态的时间
ptr_frame.setDurationToBackHeader(200);
ptr_frame.setDurationToBackFooter(200);
其中ptr_frame是PtrFrameLayout控件(即xml中使用的view)。
上面两种配置方法中用到了下面这些配置:
- 阻尼系数
默认: 1.7f,越大,感觉下拉时越吃力。
- 触发刷新时移动的位置比例
默认,1.2f,移动达到头部高度1.2倍时可触发刷新操作。
- 回弹延时
默认 200ms,回弹到刷新高度所用时间
- 头部回弹时间
默认1000ms
- 刷新时保持头部
默认值 true.
- 下拉刷新 / 释放刷新
默认为释放刷新
- 属性配置完成后再进行下一步 添加头部刷新布局,如下所示:
// Matrial风格头部的实现
final MaterialHeader header = new MaterialHeader(this);
header.setPadding(0, PtrLocalDisplay.dp2px(15),0,0);
ptr_frame.setHeaderView(header);
ptr_frame.addPtrUIHandler(header);
当然有其他的风格的头布局,你们自己找自己喜欢的添加即可。
- 头布局添加完后再添加尾布局实现加载更多,如下:
// 经典的底部布局实现
PtrClassicDefaultFooter footer = new PtrClassicDefaultFooter(this);
footer.setPadding(0, PtrLocalDisplay.dp2px(15),0,0);
ptr_frame.setFooterView(footer);
ptr_frame.addPtrUIHandler(footer);
这里底部布局暂时就一种,是默认的。
当头布局和尾布局都添加后,再添加最后一个方法就可以实现下拉刷新和上拉加载了,这里也有两种方法可以实现
一种是用PtrDefaultHandler2:实现了默认的 checkCanDoLoadMore() 逻辑,可以适用于大部分的View。如下:
/**
* 不用判断什么时候刷新和加载,方法里有自己的判断,适合大多数的情况。你只需要关心刷新和加载需要执行什么操作
*/
ptr_frame.setPtrHandler(new PtrDefaultHandler2() {
// 加载更多开始会执行该方法
@Override
public void onLoadMoreBegin(PtrFrameLayout frame) {
// 这里做一些加载的操作
// LoadMore();
// 用于关闭上拉加载
ptr_frame.refreshComplete();
}
// 刷新开始会执行该方法
@Override
public void onRefreshBegin(PtrFrameLayout frame) {
// 这里做一些刷新操作
// Refresh();
// 用于关闭下拉刷新
ptr_frame.refreshComplete();
}
});
还有一种是PtrHandler2,该方法你可以自己判断刷新和加载的逻辑,扩展性的体现,特殊情况会用到该方法的实现:
/**
* 下拉刷新和上拉加载更多的实现
* 这里你可以自己判断什么时候刷新和加载 特殊情况也不用怕有问题
*/
ptr_frame.setPtrHandler(new PtrHandler2() {
// 判断是否可以上拉加载 这里用户可以自己控制什么时候做加载操作
// 返回true表示可以加载,返回false表示不可以加载
@Override
public boolean checkCanDoLoadMore(PtrFrameLayout frame, View content, View footer) {
return true;
}
// 加载更多开始会执行该方法
@Override
public void onLoadMoreBegin(PtrFrameLayout frame) {
// 这里做一些加载的操作
// LoadMore();
// 用于关闭上拉加载
ptr_frame.refreshComplete();
}
// 判断是否可以下拉刷新 这里用户可以自己控制什么时候做刷新操作
// 返回true表示可以刷新,返回false表示不可以刷新
@Override
public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
return true;
}
// 刷新开始会执行该方法
@Override
public void onRefreshBegin(PtrFrameLayout frame) {
// 这里做一些刷新操作
// Refresh();
// 用于关闭下拉刷新
ptr_frame.refreshComplete();
}
});
- 还有一个很好的方法,你可以任意的开启/关闭header或者footer如下:
setMode(Mode): 通过调用setMode, 你可以任意的开启/关闭header或者footer。参数类型是一个枚举变量,可以通过以下方式调用:setMode(Mode.BOTH).
上面这些步骤做完,就基本实现了刷新和加载功能。
- 最后给出demo的实现代码,这里大家可以做参考:
package com.example.demo.ultrapulltorefreshdemo;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import in.srain.cube.views.ptr.PtrClassicDefaultFooter;
import in.srain.cube.views.ptr.PtrDefaultHandler2;
import in.srain.cube.views.ptr.PtrFrameLayout;
import in.srain.cube.views.ptr.PtrHandler2;
import in.srain.cube.views.ptr.header.MaterialHeader;
import in.srain.cube.views.ptr.util.PtrLocalDisplay;
public class MainActivity extends Activity {
private PtrFrameLayout ptr_frame;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取PtrFrameLayout控件
ptr_frame = (PtrFrameLayout) findViewById(R.id.ptr_frame);
// PtrFrameLayout属性设置及刷新加载的实现
setPtrFrameAttribute();
}
/***
* 必要属性设置及刷新加载的实现
*/
private void setPtrFrameAttribute() {
// 头部阻尼系数
ptr_frame.setResistanceHeader(1.7f);
// 底部阻尼系数
ptr_frame.setResistanceFooter(1.7f);
// 默认1.2f,移动达到头部高度1.2倍时触发刷新操作
ptr_frame.setRatioOfHeaderHeightToRefresh(1.2f);
// 头部回弹时间
ptr_frame.setDurationToCloseHeader(1000);
// 底部回弹时间
ptr_frame.setDurationToCloseFooter(1000);
// 释放刷新
ptr_frame.setPullToRefresh(false);
// 释放时恢复到刷新状态的时间
ptr_frame.setDurationToBackHeader(200);
ptr_frame.setDurationToBackFooter(200);
// Matrial风格头部的实现
final MaterialHeader header = new MaterialHeader(this);
header.setPadding(0, PtrLocalDisplay.dp2px(15),0,0);
ptr_frame.setHeaderView(header);
ptr_frame.addPtrUIHandler(header);
// 经典的底部布局实现
PtrClassicDefaultFooter footer = new PtrClassicDefaultFooter(this);
footer.setPadding(0, PtrLocalDisplay.dp2px(15),0,0);
ptr_frame.setFooterView(footer);
ptr_frame.addPtrUIHandler(footer);
// 设置支持刷新和加载更多 可以任意开启或者关闭某一个特性(开关)
ptr_frame.setMode(PtrFrameLayout.Mode.BOTH);
// 进入界面自动刷新
ptr_frame.post(new Runnable() {
@Override
public void run() {
// 进入界面自动刷新
ptr_frame.autoRefresh();
}
});
/**
* 下拉刷新和上拉加载更多的实现
* 这里你可以自己判断什么时候刷新和加载 特殊情况也不用怕有问题
*/
/**
ptr_frame.setPtrHandler(new PtrHandler2() {
// 判断是否可以上拉加载 这里用户可以自己控制什么时候做加载操作
// 返回true表示可以加载,返回false表示不可以加载
@Override
public boolean checkCanDoLoadMore(PtrFrameLayout frame, View content, View footer) {
return true;
}
// 加载更多开始会执行该方法
@Override
public void onLoadMoreBegin(PtrFrameLayout frame) {
// 这里做一些加载的操作
// LoadMore();
// 用于关闭上拉加载
ptr_frame.refreshComplete();
}
// 判断是否可以下拉刷新 这里用户可以自己控制什么时候做刷新操作
// 返回true表示可以刷新,返回false表示不可以刷新
@Override
public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
return true;
}
// 刷新开始会执行该方法
@Override
public void onRefreshBegin(PtrFrameLayout frame) {
// 这里做一些刷新操作
// Refresh();
// 用于关闭下拉刷新
ptr_frame.refreshComplete();
}
});
**/
/**
* 不用判断什么时候刷新和加载,方法里有自己的判断,适合大多数的情况
*/
ptr_frame.setPtrHandler(new PtrDefaultHandler2() {
// 加载更多开始会执行该方法
@Override
public void onLoadMoreBegin(PtrFrameLayout frame) {
// 这里做一些加载的操作
// LoadMore();
// 用于关闭上拉加载
ptr_frame.refreshComplete();
}
// 刷新开始会执行该方法
@Override
public void onRefreshBegin(PtrFrameLayout frame) {
// 这里做一些刷新操作
// Refresh();
// 用于关闭下拉刷新
ptr_frame.refreshComplete();
}
});
}
}
上面的代码我就不详细解释了,注释很详细,大家去实现一次就会更加熟悉。多使用吧!
==================================