很早以前,上拉加載下拉刷新這種交互方式一經推出,就火炸了。若是你在兩三年前就接觸過android開發,你必定據說過PullToRefreshListView這個開源框架,使用起來很簡單,首先感謝偉大的做者開源這麼優秀的做品,可是對於新手來說,這個框架有些過於龐大了,類和方法實在太多,定製功能太複雜,而且不得不說,再使用過程當中,這個框架的侷限性很大,說到底他只是個ListView,當你和其餘可滑動控件一塊兒套用時,就會出現各類的問題,而且這個框架的做者已經好幾年沒有維護過他了。
我在git上嘗試查找能替代他的傢伙,萬幸這個傢伙被我成功發現了。雖然他的歲數也已經很大了,但到如今我仍然在使用而且也一直在維護他的代碼。android-Ultra-Pull-To-Refresh,一樣感謝liaohuqiu貢獻這麼優秀的做品。我習慣叫這個框架爲Ptr,至於爲何到如今我還要推薦這個框架,請聽我慢慢道來:javascript
那麼他沒有缺點嗎?固然有!java
我不會對做者的源碼進行解析,畢竟網上的輪子已經不少了,重複造輪子是可恥的。也不會把修改源碼的過程進行講解,爲啥?由於很早以前就改好了,到如今已經忘了具體的過程。。。哈!Sorry,這篇文章我會盡力展現框架的結構和使用方式,幫助你更好理解Ptr的優點,思路是最重要的,代碼並不重要!android
gif中我展現了上拉加載,下拉刷新,標準,所有功能,空View五種狀況。這裏只是爲了展現,其實咱們在使用過程當中,基本不會用到各類狀況之間的互相切換。項目中目前只定義了兩種樣式的頭部,第一種就是相似gif中MaterialDesign的樣式,第二種就是傳統樣式相似PullToRefreshListView中的,這裏沒有展現。git
<com.leinyo.superptrwithrv.widget.ptr.PullToRefreshView
android:id="@+id/pull_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:ptr_refresh_mode="none"
app:ptr_scrollable="true"
/>複製代碼
此處不廢話,講解屬性含義:github
<declare-styleable name="PullToRefreshView">
<attr name="ptr_refresh_mode" format="enum">
<enum name="none" value="0"/>
<enum name="pull_from_start" value="1"/>
<enum name="pull_from_end" value="2"/>
<enum name="both" value="3"/>
</attr>
<attr name="ptr_check_login" format="boolean"/>
<attr name="ptr_header_mode" format="enum">
<enum name="material" value="0"/>
<enum name="normal" value="1"/>
</attr>
<attr name="ptr_padding_left" format="integer"/>
<attr name="ptr_padding_right" format="integer"/>
<attr name="ptr_scrollable" format="boolean"/>
</declare-styleable>複製代碼
下拉刷新對應回調接口:設計模式
public interface OnPullRefreshListener {
void onPullRefresh();
}複製代碼
onPullRefresh()方法會在刷新動畫達到臨界值之後回調。
取消下拉動畫方法:架構
public void onPullRefreshComplete() {
mPtrFrameLayout.refreshComplete();
}複製代碼
上拉加載對應回調接口:app
public interface OnLoadMoreListener {
void onLoadMoreRefresh();
}複製代碼
取消上拉動畫方法:框架
public void onLoadMoreComplete(boolean hasMore) {
mLoadMoreRecyclerViewContainer.loadMoreFinish(hasMore);
}複製代碼
boolean值 表明是否還能夠繼續上拉 false 不會再回調onLoadMoreRefresh()!!!佈局
both對應回調接口:
public interface OnRefreshListener {
void onPullRefresh();
void onLoadMoreRefresh();
}複製代碼
取消所有動畫方法:
public void onLoadComplete(boolean hasMore) {
mLoadMoreRecyclerViewContainer.loadMoreFinish(hasMore);
if (mCurrentRefreshMode == REFRESH_FROM_START) {
if (isRefreshing()) {
mPtrFrameLayout.refreshComplete();
}
}
}複製代碼
若是咱們的返回的數據是空的,須要顯示一個空頁面。咱們不須要控制兩個View的show與gone,ListView能作的咱們一樣能到。mPullView.addEmptyView(mEmpty);
注意:addEmptyView方法不能在顯示以前設置,不然會先顯示空View。爲啥,後面再說。
一樣ListView能作的咱們也能夠。mPullView.addHeaderView(mHeadView);
這一部分必定是要上圖的,說多少都是無心的。
這部分你最好對Ptr有了解
怎麼樣?一張圖是否是已經足夠清楚了?看到如今你是否已經感嘆做者的設計能力了?再看看上面說到做者在issues裏已經回覆的:下拉刷新和加載更多,不是同一個層級的功能。加載更多不該該由 UltraPTR 去實現,而應該由 Content本身去實現。
每一層級,只對應本身的業務邏輯,並不關心其餘人在幹什麼,這就叫單一職責,解耦合。
原本以爲這裏應該是講得最多的,可是寫到這裏,發現實在沒啥可說的了,若是你真的看過Ptr的源碼,相信到這裏你也已經沒有疑惑了,並且有種神清氣爽的感受,其實就是這麼簡單,代碼設計很重要,這也是爲啥有的代碼讓人看得很爽,有的代碼讓人看了想吐
咱們上面說過真正負責顯示佈局的是RecyclerView了,怎麼顯示?固然是交給Adapter就能夠了,多佈局顯示使用RecyclerView.Adapter的getItemViewType(int position)。須要記住的是:
咱們抽出基類BaseRefreshAdapter,裏面對多佈局顯示有一些基礎的操做,須要子類繼承咱們抽出基類BaseRefreshAdapter,並實現onCreateHolder(ViewGroup parent, int viewType)(他等同於onCreateViewHolder(ViewGroup parent, int viewType))和onBindHolder(VH holder, int position)(等同於onBindViewHolder(RecyclerView.ViewHolder holder, int position)),在子類中你只須要關心你本身的Item佈局就能夠了,其餘交給BaseRefreshAdapter中的邏輯就能夠了。
這裏面有泛型定義,看看源碼很好理解。
這就不難理解爲啥上面說過addEmptyView方法不能在顯示佈局以前設置了,由於若是你初始化就執行addEmptyView方法,那麼當adapter初始化時,就會執行onCreateViewHolder()一系列方法,這樣立刻就會顯示EmptyView了,等你的真正須要的數據返回纔會刷新數據佈局。
本人並未側重講解怎麼封裝,怎麼修改源碼適配RecyclerView,也並未拆源碼講解Ptr原理,也但願你們能理解,時間有點緊,並且輪子不少,不想再造了。
我但願若是你看到最後,這篇文章會對你有所幫助,學習人家的設計模式的同時,你也獲得了一個支持多種功能,基於RecyclerView的再封裝Ptr框架(感受好繞口啊),至於爲什麼叫SuperPtr,純碎是爲了好玩。。。
若是您在使用過程當中,有疑問和改進意見歡迎聯繫我。
SupterPtr 對您的支持我深表感謝,喜歡請您star哦~~