开发笔记之打造通用下拉刷新(介绍篇)
开发笔记之打造通用下拉刷新(细节篇)
开发笔记之打造通用下拉刷新(重难点篇)
前言
下拉刷新几乎是移动应用最常见的功能了,以前写一些小应用都是直接用别人写的好的库,作为开发者和初学者,我们应该要熟悉每个用过的轮子。安卓平台的下拉刷新,最近了解到比较有名的就是超过4000star 的android-Ultra-Pull-To-Refresh 了。但让人无奈的是,这么优秀的一个库,水平有限的我看源码看得头晕目眩,里面有很多的坐标判断和运算而且没有太多的注释,所以我决定试着自己造一个,于是就有了下面的PullToRefresh(名字比较随意-_-#)
PullToRefresh
源码地址: https://github.com/dzysghr/PullToRefresh
通用的可自定义头部下拉刷新布局,只实现下拉逻辑,不实现下拉头部视觉效果,功能设计参考android-Ultra-Pull-To-Refresh ,但有自己特色和优化,由于用到了ValueAnimaton,最低只能兼容3.0,不断改进中。当然写这个库更多的是出于学习和研究而不是使用的目的
主要功能特性
- 下拉松手刷新
- 下拉刷新
- 头部固定
- 内容固定
- 刷新时是否可拖动头部
- 开始刷新时是否强制回到刷新线
- 刷新完成是否强制返回
- 刷新时是否隐藏头部
- ViewPager等横向滑动控件共存(效果比android-Ultra-Pull-To-Refresh更好)
- 自动刷新
Demo
- 下拉松手刷新
- 超过刷新线刷新
- 头部固定
- 内容固定
- 刷新时隐藏头部
- viewpager等横向滑动兼容
- 刷新完成强制返回
- 自动刷新
功能配置
- 释放刷新or下拉刷新(默认为
false
,释放刷新)
mPullToRefreshLayout.setRefreshImmediately(boolean b);
- 头部固定(默认为
false
)
mPullToRefreshLayout.setPinHeader(true);
- 内容固定(默认为
false
,开启后建议关闭setCanScrollWhenRefreshing
)
mPullToRefreshLayout.setPinContent(true);
- 刷新完成强制返回(默认为
false
)
mPullToRefreshLayout.setForceToTopWhenFinish(true);
- 刷新时是否可拖动头部(默认为
true
)
mPullToRefreshLayout.setCanScrollWhenRefreshing(false);
- 触发刷新时是否强制回到刷新线(默认为
false
)
mPullToRefreshLayout.setUpToRefredshingImmediately(false);
- 开启横向滑动处理(默认为
false
,不处理横向逻辑)
mPullToRefreshLayout.setHasHorizontalChild(true);
- 上升动画时间(默认为
500ms
)
mPullToRefreshLayout.setAnimDuration(int animDuration)
- 滑动阻尼,默认为
2
mPullToRefreshLayout.setResistance(float resistance)
自定义头部
- 继承View or ViewGroup ,并实现HeaderController接口,详见demo
public interface HeaderController
{
/**
* 触发刷新的下拉高度,单位px,小于等于你的header高度
* @return 触发刷新的下拉高度
*/
int getThresholdHeight();
/**
* 正在刷新时的高度,单位px,小于等于你的header高度
* @return 正在刷新时的高度
*/
int getRefreshingHeight();
/**
* 当header的状态改变时会调用
*
* @param state 状态
*/
void StateChange(HeaderState state);
/**
* 开始刷新时被调用,这在个方法实现正在刷新时的动画
*/
void startRefresh();
/**
* 刷新成功时,此方法被调用
*/
void onSucceedRefresh();
/**
* 刷新失败时,此方法被调用
*/
void onFailRefresh();
/**
* 发生拖拽时时此方法会被PullToRefreshLayout调用,可以通过这个偏移量和当前的状态来决定动画的样子
* @param offset 当头部不固定时表示位置偏移量,当头部内容固定时表示头部露出的高度
* 范围为下拉时从 0 到 header.getMeasureHeight,上升反之。**/
void onPositionChange(float offset);
/** 当 Controller被设置到PullToRefreshLayout时调用
* @param layout 关联的PullToRefreshLayout
*/
void attachLayout(PullToRefreshLayout layout);
}
- 为PullToRefhreshLayout设置头部
mLayout.setHeader(new CustomHeader(context));
注意事项
- PullToRefreshLayout只能有一个直接子View,
- 如果子view是一个可以scroll的控件(比如ListView、RecycleView、ScrollView),PullToRefreshLayout可以直接判断子view是否已经滑到顶部,但当子view为一个XXLayout内部包含一个ListView时
PullToRefreshLayout
FrameLauout
ListView
PullToRefreshLayout是无法判断Listview是否滑到顶的,此时需要自己实现何时应该开启下拉
mPullToRefreshLayout.setScrollableListener(new ScrollCondition() {
@Override
public boolean canRefresh()
{
if(canscroll)
return false;
return true;
}
});
后记
其实我个人是不太喜欢看这种瑞士军刀式的控件源码的。因为这个控件的开发往往没有太多面向对象的思想,更多的是坐标运算和判断,由于它要做到功能强大,可配置性强,这样就导致代码里有太多的条件分支,如果做抽象又容易跟进去跟着跟着就不知道自己走到哪了,如果一个大方法写上百行又不可维护,而我们往往只会用到其中的一种功能,从而使很多判断是没必要的,十分影响对源码的理解,所以我的代码里写了很多注释,代码质量有待慢慢提高。
不过造轮子还是有好处的,当我写完这个库时或者写的过程到遇到问题,由于有了整体的思路,这时再去看Ultra Pull To Refresh源码就会感觉逻辑十分清晰,很快就找到关键的代码所在,这样一来既可以更深入地理解别人优秀的代码,又可以知道这个东西的坑在哪里但又不会在坑里困扰太久,这也是造轮子的好处吧。
后续更新中...
网友评论