GitHub:liaohuqiu/android-Ultra-Pull-To-Refresh
推荐阅读:
【框架学习】【android-Ultra-Pull-To-Refresh】
我眼中的下拉刷新
android-Ultra-Pull-To-Refresh的特点是:内置各种下拉刷新交互风格。遗憾的是这个库不支持上拉加载更多。
Android studio使用,可直接添加依赖:
compile 'in.srain.cube:ultra-ptr:1.0.11'
android-Ultra-Pull-To-Refresh (简称 UltraPTR )是一个强大的 Andriod 下拉刷新框架。
1.继承自ViewGroup,Content可以包含任何View;
2.简洁完善的Header抽象,方便进行扩展,构建满足需求的Header;
对比于Android-PullToRefresh 来说,UltraPTR没有实现上拉加载,作者认为上拉加载于下拉刷新不是同一个层次的功能,上拉加载应该交由Content自己去实现;Googgle官方的SwipeRefreshLayout也是这样认为的,对比SwipeRefreshLayout,UltraPTR更加灵活,更容易扩展。
UltraPTR首先抽象出两个接口,功能接口和UI接口
PtrHandler代表下拉刷新的功能接口,包含刷新功能回调方法以及判断是否可以下拉的方法,用户实现此接口来进行数据刷新工作。
PtrUIHandler代表下拉刷新的UI接口,包含准备下拉、下拉中、下拉完成、下拉重置以及下拉过程中的位置变化等回调方法。通常情况下,Header需要实现此接口,来处理下拉刷新过程中头部UI的变化。
整个项目围绕核心类PtrFrameLayout。
PtrFrameLayout代表了一个下拉刷新的自定义控件。
PtrFrameLayout继承自ViewGroup,有且只能有两个子View,头部Header和内容Content。通常情况下,Header会实现PtrUIHandler接口,Content可以为任意的View。
和所有的自定义控件一样,PtrFrameLayout通过重写onFinishInflate、onMeasure、onLayout来确定控件的大小和位置,通过重写dispatchTouchEvent来确定控件的下拉行为。
//使用上主要分四步
//1、设置头部
initHeaders();
//2、添加头部
ptrFrameLayout.setHeaderView(header);
//3、处理下拉刷新过程中头部UI的变化
ptrFrameLayout.addPtrUIHandler(header);
//4、判断是否可以下拉,数据刷新工作。
ptrFrameLayout.setPtrHandler(new PtrHandler() {
//判断是否可以下拉刷新。
//UltraPTR 的 Content 可以包含任何内容,用户在这里判断决定是否可以下拉。
//例如,如果 Content 是 TextView,则可以直接返回 true,表示可以下拉刷新。
//如果 Content 是 ListView,当第一条在顶部时返回 true,表示可以下拉刷新。
//如果 Content 是 ScrollView,当滑动到顶部时返回 true,表示可以刷新。
@Override
public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
return true;
}
//开始刷新:刷新回调函数,
//用户在这里写自己的刷新功能实现,处理业务数据的刷新。
@Override
public void onRefreshBegin(PtrFrameLayout frame) {
progressBar.setVisibility(View.VISIBLE);
handler.postDelayed(new Runnable() {
@Override
public void run() {
updateData(true);
}
}, 3000);
}
});
/**
* //第一种头部
* StoreHouse风格的头部实现
*/
storeHouseHeader = new StoreHouseHeader(this);
storeHouseHeader.setBackgroundColor(Color.BLACK);
storeHouseHeader.setTextColor(Color.WHITE);
storeHouseHeader.setLineWidth(5);
storeHouseHeader.initWithString("ENGLISH ONLY HAHA"); //只可英文,中文不可运行(添加时间)
//"last update @" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())
/**
* //第二种头部
* Material Design风格的头部实现
*/
materialHeader = new MaterialHeader(this);
materialHeader.setColorSchemeColors(new int[]{Color.RED, Color.GREEN, Color.BLUE});//类似SwipeRefreshLayout
/**
* //第三种头部
* 经典 风格的头部实现
*/
ptrClassicDefaultHeader = new PtrClassicDefaultHeader(this);
阻尼系数:Resistance
//默认: 1.7f,越大,感觉下拉时越吃力。
触发刷新时移动的位置比例:RatioOfHeaderHeightToRefresh
//默认,1.2f,移动达到头部高度1.2倍时可触发刷新操作。
回弹延时:DurationToClose
//默认 200ms,回弹到刷新高度所用时间
头部回弹时间:DurationToCloseHeader
//默认1000ms
刷新是保持头部:KeepHeaderWhenRefresh
//默认值 true.
下拉刷新 / 释放刷新:PullToRefresh
//默认为释放刷新,默认false
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>
java代码中也可设置头部参数:
// the following are default settings
mPtrFrame.setResistance(1.7f);
mPtrFrame.setRatioOfHeaderHeightToRefresh(1.2f);
mPtrFrame.setDurationToClose(200);
mPtrFrame.setDurationToCloseHeader(1000);
// default is false
mPtrFrame.setPullToRefresh(false);
// default is true
mPtrFrame.setKeepHeaderWhenRefresh(true);
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ptr="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=".MainActivity">
<in.srain.cube.views.ptr.PtrFrameLayout
android:id="@+id/ptrFrameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
ptr:ptr_keep_header_when_refresh="true"
ptr:ptr_pull_to_fresh="false"
ptr:ptr_ratio_of_header_height_to_refresh="1.2"
ptr:ptr_resistance="1.7">
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</in.srain.cube.views.ptr.PtrFrameLayout>
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
<ImageButton
android:id="@+id/btnBack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_margin="@dimen/btnBackMargin"
android:src="@mipmap/ic_launcher" />
</RelativeLayout>
package com.example.administrator.myapplication;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.SimpleAdapter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import in.srain.cube.views.ptr.PtrClassicDefaultHeader;
import in.srain.cube.views.ptr.PtrDefaultHandler;
import in.srain.cube.views.ptr.PtrFrameLayout;
import in.srain.cube.views.ptr.PtrHandler;
import in.srain.cube.views.ptr.header.MaterialHeader;
import in.srain.cube.views.ptr.header.StoreHouseHeader;
import in.srain.cube.views.ptr.util.PtrLocalDisplay;
/**
* Created by Administrator on 2017/5/11.
*/
public class PtrActivity extends AppCompatActivity {
private PtrFrameLayout ptrFrameLayout;
private ListView listView;
private ProgressBar progressBar;
private ImageButton btnBack;
private List<Map<String, String>> data;
private Handler handler = new Handler();
private SimpleAdapter adapter;
private StoreHouseHeader storeHouseHeader;
private MaterialHeader materialHeader;
private PtrClassicDefaultHeader ptrClassicDefaultHeader;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ptr_layout);
findViews();
initData();
initPtrRefresh();
initBtnBack();
}
//第三步:
private void initPtrRefresh() {
//第3.1步:
initHeaders();
// ptrFrameLayout.setHeaderView(ptrClassicDefaultHeader);
// ptrFrameLayout.addPtrUIHandler(ptrClassicDefaultHeader);
// ptrFrameLayout.setHeaderView(storeHouseHeader);
// ptrFrameLayout.addPtrUIHandler(storeHouseHeader);
ptrFrameLayout.setHeaderView(materialHeader);//类似SwipeRefreshLayout
ptrFrameLayout.addPtrUIHandler(materialHeader);
ptrFrameLayout.setPtrHandler(new PtrHandler() {
//检查是否可以刷新
@Override
public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
return true;
}
//开始刷新
@Override
public void onRefreshBegin(PtrFrameLayout frame) {
progressBar.setVisibility(View.VISIBLE);
handler.postDelayed(new Runnable() {
@Override
public void run() {
//第3.2步:
updateData(true);
}
}, 3000);
}
});
}
//第3.1步:
private void initHeaders() {
/**
* //第一种头部
* StoreHouse风格的头部实现
*/
storeHouseHeader = new StoreHouseHeader(this);
storeHouseHeader.setBackgroundColor(Color.BLACK);
storeHouseHeader.setTextColor(Color.WHITE);
storeHouseHeader.setLineWidth(5);
storeHouseHeader.initWithString("ENGLISH ONLY HAHA"); //只可英文,中文不可运行(添加时间)
//"last update @" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())
/**
* //第二种头部
* Material Design风格的头部实现
*/
materialHeader = new MaterialHeader(this);
materialHeader.setColorSchemeColors(new int[]{Color.RED, Color.GREEN, Color.BLUE});//类似SwipeRefreshLayout
/**
* //第三种头部
* 经典 风格的头部实现
*/
ptrClassicDefaultHeader = new PtrClassicDefaultHeader(this);
}
//第3.2步:
private void updateData(boolean addToTop) {
HashMap<String, String> map = new HashMap<>();
if (addToTop) {
map.put("key", "im added head");
((LinkedList) data).addFirst(map);
} else {
map.put("key", "im added tail");
((LinkedList) data).addLast(map);
}
adapter.notifyDataSetChanged();
progressBar.setVisibility(View.GONE);
ptrFrameLayout.refreshComplete();
}
//第四步
private void initBtnBack() {
btnBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// listView.setSelection(0);
listView.smoothScrollToPosition(0);
}
});
}
//第一步:
private void findViews() {
ptrFrameLayout = ((PtrFrameLayout) findViewById(R.id.ptrFrameLayout));
listView = ((ListView) findViewById(R.id.listView));
progressBar = ((ProgressBar) findViewById(R.id.progressBar));
btnBack = ((ImageButton) findViewById(R.id.btnBack));
progressBar.setVisibility(View.GONE);
}
//第二步:
private void initData() {
data = new LinkedList<>();
for (int i = 0; i < 20; i++) {
HashMap<String, String> map = new HashMap<>();
map.put("key", "im item " + i);
data.add(map);
}
adapter = new SimpleAdapter(this, data,
android.R.layout.simple_list_item_1, new String[]{"key"}, new int[]{android.R.id.text1});
listView.setAdapter(adapter);
}
}
android-Ultra-Pull-To-Refresh 使用简介
android-Ultra-Pull-To-Refresh 的基本用法(适合于初学者)
GitHub地址:captainbupt/android-Ultra-Pull-To-Refresh-With-Load-More
compile 'in.srain.cube:ptr-load-more:1.0.6'
同android-Ultra-Pull-To-Refresh
唯一区别:
/*支持上拉加载,下拉刷新*/
ptrFrameLayout.setPtrHandler(new PtrDefaultHandler2() {
@Override
public void onLoadMoreBegin(PtrFrameLayout frame) {
updateData(false);
}
@Override
public void onRefreshBegin(PtrFrameLayout frame) {
updateData(true);
}
});
/*仅支持下拉刷新*/
ptrFrameLayout.setPtrHandler(new PtrDefaultHandler() {
@Override
public void onRefreshBegin(PtrFrameLayout frame) {
}
});
Ultra-Pull-To-Refresh上拉加载的使用
UltraPullToRefreshWithLoadMore (为UltraPullToRefresh添加上拉加载更多功能)