【轉載請註明出處】html
本文將說明具備多個section的UITableView在使用下拉刷新機制時會遇到的問題及其解決方案。git
工程地址在帖子最下方,只須要代碼的直拉到底便可。github
【目錄】post
一、現象分析;ui
二、解決方案;url
三、工程地址。 spa
一、現象分析
當前的大多數支持下拉刷新的庫,都是經過修改UIScrollView的contentInset實現的。3d
(可參見個人這篇帖子:UITableView:下拉刷新和上拉加載更多)code
使用這種方法帶來的問題是,當UITableView具備多個section時,依照上述方式使用下拉刷新,在加載過程當中上滑,會出現樣式跑版:htm
爲了分析出問題所在,首先在控制檯打印出正常狀態下UITableView的全部子View :
比較各行的frame.origin.y能夠看出,UITableView的section headerView是和cell一塊兒,按順序放入基類UIScrollView的內容View中的。
再看加載中時的狀況:
從Pull2RefreshView的frame能夠看出,此時UITableView的contentInset已經被修改成(65, 0, 0, 0)。而section headerView和各個cell的frame.origin.y不受影響,和預期一致。
最後看看在加載中狀態下上滑時的狀況,將UITableView上滑至上方圖中所示情境,即第一行的cell剛恰好越過section headerView:
能夠看到,section headerView的frame.origin.y發生了變化,它和第二個cell一塊兒被放在了第一個cell的下方,即:
section headerView.frame.origin.y == firstCell.frame.origin.y + cellHeight;
繼續上滑,能夠看到section headerView.frame.origin.y不斷變化,但在界面顯示上,始終位於距離UITableView.frame.origin.y爲65(即修改後contengInset.top的值)的位置,直到下一個section headerView出現時,才隨着cell向上移動,如圖:
【注意:不論在任何狀況下,第一個cell的frame.origin.y始終爲section headerView的高度,在本例中爲23,即便它已經處於section headerView的上方】
二、解決方案
由此,能夠粗略得出如下結論:
A、 section headerView和cell之間並非簡單的順序擺放的關係,它們之間能夠發生重疊;
B、 section headerView在界面上的顯示位置由UITableView.contentInset.top決定,直到被下一個section headerView替代。
如此,想要在滑動時修改section headerView的顯示位置,令其和cell一塊兒移動,只須要動態地修改UITableView.contentInset.top便可,以下:
Added 2014.7.24:
對於不須要提交到AppStore的應用,還有一個更簡單的辦法,即覆蓋UITableView的私有方法。
- (BOOL)allowsHeaderViewsToFloat { return NO; } - (BOOL)allowsFooterViewsToFloat { return NO; }
三、工程地址
使用iOS 6.1 SDK編譯,使用ARC。
地址:https://github.com/cDigger/CDPullToRefreshDemo
【參考】
一、Section Headers in UITableView when inset of tableview is changed
二、Change Default Scrolling Behavior of UITableView Section Header