下拉刷新和UITableView的section headerView衝突的緣由分析與解決方案

UITableView:下拉刷新和上拉加載更多

【轉載請註明出處】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便可,以下:

 1  - ( void)scrollViewDidScroll:(UIScrollView *)scrollView
 2   {
 3        // added 2013.11.28 動態修改headerView的位置
 4        if (headerRefreshing)
 5       {
 6            if (scrollView.contentOffset.y >= -scrollView.contentInset.top
 7               && scrollView.contentOffset.y <  0)
 8           {
 9                // 注意:修改scrollView.contentInset時,若使當前界面顯示位置發生變化,會觸發scrollViewDidScroll:,從而致使死循環。
10                // 所以此處scrollView.contentInset.top必須爲-scrollView.contentOffset.y
11              scrollView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y,  000);
12          }
13           else  if (scrollView.contentOffset.y ==  0) // 到0說明headerView已經在tableView最上方,不須要再修改了
14          {
15              scrollView.contentInset = UIEdgeInsetsZero;
16          }
17      }
18      
19       // other code here...
20  }

 

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

http://stackoverflow.com/questions/5466097/section-headers-in-uitableview-when-inset-of-tableview-is-changed 

二、Change Default Scrolling Behavior of UITableView Section Header

http://stackoverflow.com/questions/664781/change-default-scrolling-behavior-of-uitableview-section-header 

相關文章
相關標籤/搜索