UITableView 下拉重新整理和上拉載入更多

2021-07-13 21:22:06 字數 3526 閱讀 3760

本文將說明讓uiscrollview支援"下拉重新整理"和"上拉載入更多"的實現機制,並實現乙個可用的tableview子類,以下主要以"下拉重新整理"進行說明。

工程位址在帖子最下方,只需要**的直拉到底即可。

1、contentinset和下拉重新整理

contentinset是uiscrollview的屬性,它描述了uiscrollview的內容view的內邊距,具體可見官方文件:

目前幾乎所有"下拉重新整理"的第三方庫都是依賴它實現的。

【為便於討論,將下拉重新整理/上拉載入時顯示的檢視稱為refresh panel,如下圖】 

在使用者手指向下滑動到最終更新介面的過程中,經歷了4個步驟:

(1)隨著使用者下拉逐漸顯示uitableview頂部的refresh panel;

(2a)下拉達到預設位置,狀態文字變為"鬆開可以重新整理";

(2b)下拉未達到預設位置,使用者手指離開螢幕,scrollview彈回,refresh panel重新隱藏起來,結束。

(3)使用者手指離開螢幕,refresh panel保持顯示。狀態文字變為"載入中",在後台執行更新資料的操作;

(4)資料更新完成,返回主線程,重新隱藏refresh panel,結束。

可以看到,如果不考慮重新整理時間、狀態文字等,實現"下拉重新整理"實際上只需要做到2件事:

(1)隱藏refresh panel(初始時和重新整理後)

隱藏refresh panel,即使其居於uitableview的上方且不可見,如下

1

- (void

)adddragheaderview2

11 }

【 注意 :不應使用uitableview的tableheaderview來作為refresh panel,一來會使得下拉重新整理和自定義tableheaderview無法共存,二來uitableview的內容檢視是包含tableheaderview的,即

tableview.contentsize.height == tableview.tableheaderview.height

+ n * sectionheaderview.height

+ m * cell.height

+ tableview.tablefooterview.height

因此想讓tableheaderview預設不可見,需要修改contentoffset的初始值並在使用者滑動時控制滑動範圍,非常麻煩。】

(2)顯示refresh panel

當使用者手指下拉達到預設值並離開螢幕,立即修改contentinset,使refresh panel保持顯示,如下

1

- (void)scrollviewdidenddragging:(uiscrollview *)scrollview willdecelerate:(bool)decelerate2

8 }

如此,更新資料後再次隱藏refresh panel的方式也很明了

1 self.contentinset = uiedgeinsetszero;
2、動畫、動態文字和重新整理時間

1

@implementation

pull2refreshview

2

在1中已經做到了refresh panel的顯示的隱藏,2中只需要在合適的時候改變refresh panel的顯示內容即可。

(1)"下拉可以重新整理"—>"鬆開立即更新"

在uiscrollview的委託函式scrollviewdidscroll:中檢測使用者下拉的程度,達到預設值後就改變狀態,如下:

1

- (void)scrollviewdidscroll:(uiscrollview *)scrollview2

14 }

15 }

修改指示箭頭方向為向上,在setstate中修改狀態文字為"鬆開立即重新整理"。

(2)"鬆開立即重新整理"—>"載入中..." 

在uiscrollview的委託函式scrollviewdidenddragging: willdecelerate:中檢測使用者手指離開螢幕時的情況:

1

- (void)scrollviewdidenddragging:(uiscrollview *)scrollview willdecelerate:(bool)decelerate2

12 }

相比1中新增了修改指示箭頭方向,在setstate中修改狀態文字為"載入中..."。

(3)"載入中..."—>"下拉可以重新整理" 

這一步需要由外部(通常是viewcontroller)判斷何時執行,提供乙個方法供外部呼叫,如下:

1

- (void

)completedragrefresh

2

指示箭頭方向和狀態文字恢復為初始狀態,更新時間變為當前時間。

3、其他 

(1)"下拉重新整理"和"上拉載入更多"的不同 

"下拉重新整理"的refresh panel的位置始終不變,而"上拉載入更多"的refresh panel則需要隨著tableview.contentsize的變化而變化。乙個比較簡單的方案是:

1 tableview.tablefooterview = dragfooterview;
在某些第三方實現中便是如此處理的,好處是簡單到只需要一行**,壞處是tablefooterview被占用了。考慮到tablefooterview在"上拉載入更多"的情境下不太需要自定義,影響不大。

另乙個方案是在初始化時和資料更新後,設定refresh panel的frame使其始終保持正確位置。

此外,在觸發重新整理的條件上,二者也是不同的。"下拉重新整理"時,為防止重新整理"太過靈敏",需要設定乙個閥值來控制,所以才有"鬆開立即重新整理"。而"上拉載入更多"是在使用者往下不斷瀏覽內容的過程中觸發的,因此只需滑動到內容底部就立即觸發載入。

uitableview作為派生類,是和基類uiscrollview共享乙個delegate屬性的,即uitableviewdeleagte和uiscrollviewdelegate是同時指定的。這帶來的問題是,想要封裝乙個支援"下拉重新整理"和"上拉載入更多"的uitableview子類,恐怕不得不增加一層委託,將uitableviewdelegate中的各種方法都轉到外部進行實現,如

1

- (void)tableview:(uitableview *)tableview didselectrowatindexpath:(nsindexpath *)indexpath2

7 }

可謂麻煩至極。暫未想到較好的解決方案。【mark】

4、封裝的pull2refreshtableview demo工程

使用ios 6.1 sdk編譯,使用arc。

1、scroll view programming guide for ios

UITableView實現下拉重新整理

uirefreshconteol類是實現下拉重新整理的控制項,並且uitableview有refreshcontrol的屬性。定義 uirefreshcontrol control uirefresh alloc init 下拉重新整理時顯示的文字 control.attributedtitle n...

UITableView實現下拉重新整理的小功能

一 找到你的 uitableview uitableviewcontroller 的 h 檔案,結合以下 新增相應的元素 import egorefreshtableheaderview.h inte ce rootviewcontroller uitableviewcontroller void ...

UITableView實現下拉重新整理新增資料功能

用uitableviewdelegate中的這個方法 void tableview uitableview tableview willdisplaycell uitableviewcell cell forrowatindexpath nsindexpath indexpath 判定tablevi...