關(guān)于MJRefresh的源碼

MJRefresh 是 OC 語言里面算是一款比較通用的刷新框架了,可以用于 UITableView 和 UICollectionView 的刷新,從而可以很方便的完成下拉刷新和上拉加載更多。而且可定制程度也很高。

最近需要在公司的項(xiàng)目上加入一個刷新的特效,而公司項(xiàng)目用的刷新框架是 MJefresh ,所以在完成需求的同時就順便把 MJRefresh 框架的源碼給看了一遍。然后寫下這篇文章總結(jié)一下。

MJRefresh框架的結(jié)構(gòu)是用子類繼承的方式實(shí)現(xiàn)的,創(chuàng)建一個基類MJRefreshComponent,然后通過繼承的方式,讓MJRefreshHeader和MJRefreshFooter分別具備下拉刷新和上拉加載的功能。從繼承機(jī)構(gòu)來看可以分為三層,具體的繼承關(guān)系可以從下面的圖里看:

其中五大核心類庫

MJRefreshComponent

MJRefreshHeader

MJRefreshFooter

MJRefreshBackFooter

MJRefreshAutoFooter

其它的類都是在上面的基礎(chǔ)上自定義的類。

首先來看一下MJRefresh框架的基類:MJRefreshComponent

MJRefreshComponent

這個類作為框架的基類,涵蓋了基類所具備的狀態(tài),回調(diào)block等,完成了以下幾件事情:

布局控件的位置。

完成基本的設(shè)置工作。

設(shè)置下拉刷新時的文本框。

設(shè)置控件的所有狀態(tài)。

設(shè)置回調(diào)函數(shù)。

添加監(jiān)聽。

提供刷新,停止刷新接口。

提供子類需要實(shí)現(xiàn)的方法。

具體實(shí)現(xiàn):

定義控件的全部的狀態(tài)

定義控件的回調(diào)函數(shù)

Target-Action類型的回調(diào)

監(jiān)聽函數(shù)的實(shí)現(xiàn)

開始刷新和停止刷新

需要子類實(shí)現(xiàn)的方法

其中代碼中作者的注解可以看出框架具體的操作對象是 scrollView 而不是具體的 tableView 和 collectionView

其中如果該類是 scrollView 或者 scrollView 子類就對其添加監(jiān)聽。

其中isKindOfClass和isMemberOfClass的區(qū)別是需要關(guān)注的。

然后MJRefreshHeader和MJRefreshFooter都繼承MJRefreshComponent實(shí)現(xiàn)。

MJRefreshHeader

MJRefreshHeader繼承MJRefreshComponent,它做了這幾件事:

初始化。

設(shè)置header高度。

重新計(jì)算下拉高度值。

記錄上一次刷新時間或者是第一次刷新時間。

由contentOffset的變化,來切換狀態(tài)(默認(rèn)狀態(tài),可以刷新的狀態(tài),正在刷新的狀態(tài)),實(shí)現(xiàn)方法是:scrollViewContentOffsetDidChange:。

在切換狀態(tài)時,執(zhí)行相應(yīng)的操作。實(shí)現(xiàn)方法是:setState:。

兩種創(chuàng)建方式(兩種構(gòu)造方法)

重寫父類方法,設(shè)置Y值 ,同時設(shè)置上次刷新時間

狀態(tài)切換

重寫控件所有狀態(tài)的set方法,設(shè)置

MJRefreshStateHeader

這個類是MJRefreshHeader類的子類,它做了兩件事:

設(shè)置stateLabel和lastUpdatedTimeLabel的位置。

根據(jù)控件狀態(tài)的切換(默認(rèn)狀態(tài),正在刷新狀態(tài)),實(shí)現(xiàn)了這兩個label顯示的文字的切換。

這里設(shè)置文字的方法有點(diǎn)兒類似按鈕。將每一個狀態(tài)對應(yīng)的提示文字放入一個字典里面,key是狀態(tài)的NSNumber形式。

布局方法

重寫set方法,更新刷新時間

1.作者通過使用block來讓用戶自己定義日期現(xiàn)實(shí)的格式,如果用戶沒有自定義,就使用作者提供的默認(rèn)格式。

2.默認(rèn)格式的設(shè)置里,判斷了是否是今日,是否是今年的情況。由具體時間顯示label的文字是否顯示年,月,日。

MJRefreshNormalHeader

MJRefreshNormalHeader 繼承 MJRefreshStateHeader,它主要做了兩件事:

它在MJRefreshStateHeader上添加了_arrowView和loadingView。

布局了這兩個view并在Refresh控件的狀態(tài)切換的時候改變這兩個view的樣式。

作者同樣是通過重寫父類的三個方法實(shí)現(xiàn)子類自定義本類的控件。

到此為止,我們已經(jīng)從MJRefreshComponent到MJRefreshNormalHeader的實(shí)現(xiàn)過程看了一遍??梢钥闯?,作者將prepare,placeSubviews以及setState:方法作為基類的方法,讓下面的子類去一層一層實(shí)現(xiàn)。

而每一層的子類,根據(jù)自身的職責(zé),分別按照自己的方式來實(shí)現(xiàn)這三個方法:

MJRefreshHeader: 負(fù)責(zé)header的高度和調(diào)整header自身在外部的位置。

MJRefreshStateHeader:負(fù)責(zé)header內(nèi)部的stateLabel和lastUpdatedTimeLabel的布局和不同狀態(tài)下內(nèi)部文字的顯示。

MJRefreshNormalHeader:負(fù)責(zé)header內(nèi)部的loadingView以及arrowView的布局和不同狀態(tài)下的顯示。

這樣做的好處是,如果想要增加某種類型的header,只要在某一層上做文章即可。例如該框架里的MJRefreshGifHeader,它和MJRefreshNormalHeader屬于同一級,都是繼承于MJRefreshStateHeader。因?yàn)槎叨季哂邢嗤问降膕tateLabel和lastUpdatedTimeLabel,唯一不同的就是左側(cè)的部分:

MJRefreshNormalHeader的左側(cè)是箭頭。

MJRefreshGifHeader的左側(cè)則是一個gif動畫。

關(guān)于兩種footerView的區(qū)別。

BackFooter 自動彈回底部

backFooter 是上拉出現(xiàn)加載 view ,然后在加載完以后就這個 view 就自動彈回底部的。即使是 tableView 或者是 collectionView 當(dāng)數(shù)據(jù)量還不足以填充滿整個界面的時候也是如此的。

Auto Footer 自動刷新

自動刷新方式是沒有明顯的上拉的動作,就是當(dāng)滑動到最底部的時候,就自動加載。而當(dāng) tableView 或者 collectionView 的數(shù)據(jù)不足以填充滿這個屏幕的時候,刷新的 view 也是現(xiàn)實(shí)在 最后一個數(shù)據(jù)項(xiàng)的下面一項(xiàng)。然后點(diǎn)擊加載更多。

總體而言,這個框架是在最基類里面實(shí)現(xiàn)了最基本的流程,而每個流程怎么處理則因?yàn)?header 和 Footer 的不同需要不同的邏輯處理。所以有 header 和 Footer 的子類。

但是由于 Footer 的上拉有兩種樣式和情況,所以在 Footer 的基礎(chǔ)上又實(shí)現(xiàn)兩個類 backFooter 和 autoFooter 。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容