下拉刷新和UITableView的section headerView沖突的原因分析與解決方案


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

【轉載請注明出處】

 

本文將說明具有多個section的UITableView在使用下拉刷新機制時會遇到的問題及其解決方案。

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

 

【目錄】

1、現象分析;

2、解決方案;

3、工程地址。 

 

1、現象分析 
當前的大多數支持下拉刷新的庫,都是通過修改UIScrollView的contentInset實現的。

(可參見我的這篇帖子:UITableView:下拉刷新和上拉加載更多

使用這種方法帶來的問題是,當UITableView具有多個section時,依照上述方式使用下拉刷新,在加載過程中上滑,會出現樣式跑版:

 

 

為了分析出問題所在,首先在控制台打印出正常狀態下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的上方】 

 

2、解決方案 

 由此,可以粗略得出以下結論:

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;
}

 

3、工程地址

使用iOS 6.1 SDK編譯,使用ARC。
地址:https://github.com/cDigger/CDPullToRefreshDemo

 

 

 

【參考】

1、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 

2、Change Default Scrolling Behavior of UITableView Section Header

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM