開發(fā)筆記之打造通用下拉刷新(介紹篇)
開發(fā)筆記之打造通用下拉刷新(細(xì)節(jié)篇)
開發(fā)筆記之打造通用下拉刷新(重難點篇)
前言
下拉刷新幾乎是移動應(yīng)用最常見的功能了,以前寫一些小應(yīng)用都是直接用別人寫的好的庫狐肢,作為開發(fā)者和初學(xué)者惠爽,我們應(yīng)該要熟悉每個用過的輪子。安卓平臺的下拉刷新瞬哼,最近了解到比較有名的就是超過4000star 的android-Ultra-Pull-To-Refresh 了婚肆。但讓人無奈的是,這么優(yōu)秀的一個庫坐慰,水平有限的我看源碼看得頭暈?zāi)垦=闲裕锩嬗泻芏嗟淖鴺?biāo)判斷和運(yùn)算而且沒有太多的注釋用僧,所以我決定試著自己造一個,于是就有了下面的PullToRefresh(名字比較隨意-_-#)
PullToRefresh
源碼地址: https://github.com/dzysghr/PullToRefresh
通用的可自定義頭部下拉刷新布局赞咙,只實現(xiàn)下拉邏輯责循,不實現(xiàn)下拉頭部視覺效果,功能設(shè)計參考android-Ultra-Pull-To-Refresh 攀操,但有自己特色和優(yōu)化院仿,由于用到了ValueAnimaton,最低只能兼容3.0速和,不斷改進(jìn)中歹垫。當(dāng)然寫這個庫更多的是出于學(xué)習(xí)和研究而不是使用的目的
主要功能特性
- 下拉松手刷新
- 下拉刷新
- 頭部固定
- 內(nèi)容固定
- 刷新時是否可拖動頭部
- 開始刷新時是否強(qiáng)制回到刷新線
- 刷新完成是否強(qiáng)制返回
- 刷新時是否隱藏頭部
- ViewPager等橫向滑動控件共存(效果比android-Ultra-Pull-To-Refresh更好)
- 自動刷新
Demo
- 下拉松手刷新
![](https://github.com/dzysghr/PullToRefresh/raw/master/gif/%E4%B8%8B%E6%8B%89%E9%87%8A%E6%94%BE%E5%88%B7%E6%96%B0_clip.gif)
- 超過刷新線刷新
![](https://github.com/dzysghr/PullToRefresh/raw/master/gif/%E8%B6%85%E8%BF%87%E5%88%B7%E6%96%B0%E7%BA%BF%E5%88%B7%E6%96%B0_clip.gif)
- 頭部固定
![](https://github.com/dzysghr/PullToRefresh/raw/master/gif/%E5%A4%B4%E9%83%A8%E5%9B%BA%E5%AE%9A_clip.gif)
- 內(nèi)容固定
![](https://github.com/dzysghr/PullToRefresh/raw/master/gif/%E5%86%85%E5%AE%B9%E5%9B%BA%E5%AE%9A_clip.gif)
- 刷新時隱藏頭部
![](https://github.com/dzysghr/PullToRefresh/raw/master/gif/%E9%9A%90%E8%97%8F%E5%A4%B4%E9%83%A8_clip.gif)
- viewpager等橫向滑動兼容
![](https://github.com/dzysghr/PullToRefresh/raw/master/gif/%E6%A8%AA%E5%90%91_clip.gif)
- 刷新完成強(qiáng)制返回
![](https://github.com/dzysghr/PullToRefresh/raw/master/gif/%E5%BC%BA%E5%88%B6%E8%BF%94%E5%9B%9E_clip.gif)
- 自動刷新
![](https://github.com/dzysghr/PullToRefresh/raw/master/gif/%E8%87%AA%E5%8A%A8%E5%88%B7%E6%96%B0_clip.gif)
功能配置
- 釋放刷新or下拉刷新(默認(rèn)為
false
,釋放刷新)
mPullToRefreshLayout.setRefreshImmediately(boolean b);
- 頭部固定(默認(rèn)為
false
)
mPullToRefreshLayout.setPinHeader(true);
- 內(nèi)容固定(默認(rèn)為
false
,開啟后建議關(guān)閉setCanScrollWhenRefreshing
)
mPullToRefreshLayout.setPinContent(true);
- 刷新完成強(qiáng)制返回(默認(rèn)為
false
)
mPullToRefreshLayout.setForceToTopWhenFinish(true);
- 刷新時是否可拖動頭部(默認(rèn)為
true
)
mPullToRefreshLayout.setCanScrollWhenRefreshing(false);
- 觸發(fā)刷新時是否強(qiáng)制回到刷新線(默認(rèn)為
false
)
mPullToRefreshLayout.setUpToRefredshingImmediately(false);
- 開啟橫向滑動處理(默認(rèn)為
false
颠放,不處理橫向邏輯)
mPullToRefreshLayout.setHasHorizontalChild(true);
- 上升動畫時間(默認(rèn)為
500ms
)
mPullToRefreshLayout.setAnimDuration(int animDuration)
- 滑動阻尼排惨,默認(rèn)為
2
mPullToRefreshLayout.setResistance(float resistance)
自定義頭部
- 繼承View or ViewGroup ,并實現(xiàn)HeaderController接口碰凶,詳見demo
public interface HeaderController
{
/**
* 觸發(fā)刷新的下拉高度,單位px,小于等于你的header高度
* @return 觸發(fā)刷新的下拉高度
*/
int getThresholdHeight();
/**
* 正在刷新時的高度,單位px暮芭,小于等于你的header高度
* @return 正在刷新時的高度
*/
int getRefreshingHeight();
/**
* 當(dāng)header的狀態(tài)改變時會調(diào)用
*
* @param state 狀態(tài)
*/
void StateChange(HeaderState state);
/**
* 開始刷新時被調(diào)用,這在個方法實現(xiàn)正在刷新時的動畫
*/
void startRefresh();
/**
* 刷新成功時欲低,此方法被調(diào)用
*/
void onSucceedRefresh();
/**
* 刷新失敗時辕宏,此方法被調(diào)用
*/
void onFailRefresh();
/**
* 發(fā)生拖拽時時此方法會被PullToRefreshLayout調(diào)用,可以通過這個偏移量和當(dāng)前的狀態(tài)來決定動畫的樣子
* @param offset 當(dāng)頭部不固定時表示位置偏移量伸头,當(dāng)頭部內(nèi)容固定時表示頭部露出的高度
* 范圍為下拉時從 0 到 header.getMeasureHeight,上升反之匾效。**/
void onPositionChange(float offset);
/** 當(dāng) Controller被設(shè)置到PullToRefreshLayout時調(diào)用
* @param layout 關(guān)聯(lián)的PullToRefreshLayout
*/
void attachLayout(PullToRefreshLayout layout);
}
- 為PullToRefhreshLayout設(shè)置頭部
mLayout.setHeader(new CustomHeader(context));
注意事項
- PullToRefreshLayout只能有一個直接子View,
- 如果子view是一個可以scroll的控件(比如ListView恤磷、RecycleView面哼、ScrollView),PullToRefreshLayout可以直接判斷子view是否已經(jīng)滑到頂部哮伟,但當(dāng)子view為一個XXLayout內(nèi)部包含一個ListView時
PullToRefreshLayout
FrameLauout
ListView
PullToRefreshLayout是無法判斷Listview是否滑到頂?shù)母藭r需要自己實現(xiàn)何時應(yīng)該開啟下拉
mPullToRefreshLayout.setScrollableListener(new ScrollCondition() {
@Override
public boolean canRefresh()
{
if(canscroll)
return false;
return true;
}
});
后記
其實我個人是不太喜歡看這種瑞士軍刀式的控件源碼的俭茧。因為這個控件的開發(fā)往往沒有太多面向?qū)ο蟮乃枷氩砑ぃ嗟氖亲鴺?biāo)運(yùn)算和判斷悔详,由于它要做到功能強(qiáng)大挪略,可配置性強(qiáng)波材,這樣就導(dǎo)致代碼里有太多的條件分支酿愧,如果做抽象又容易跟進(jìn)去跟著跟著就不知道自己走到哪了游岳,如果一個大方法寫上百行又不可維護(hù)政敢,而我們往往只會用到其中的一種功能,從而使很多判斷是沒必要的胚迫,十分影響對源碼的理解喷户,所以我的代碼里寫了很多注釋,代碼質(zhì)量有待慢慢提高访锻。
不過造輪子還是有好處的褪尝,當(dāng)我寫完這個庫時或者寫的過程到遇到問題闹获,由于有了整體的思路,這時再去看Ultra Pull To Refresh源碼就會感覺邏輯十分清晰河哑,很快就找到關(guān)鍵的代碼所在避诽,這樣一來既可以更深入地理解別人優(yōu)秀的代碼,又可以知道這個東西的坑在哪里但又不會在坑里困擾太久璃谨,這也是造輪子的好處吧沙庐。
后續(xù)更新中...