2012-03-17 45 views
0

我有一個具有表格視圖的VC。當發生事件時,我想從主視圖的頂部放入一個UIView。當用戶滾動表格視圖時,我想重新佈局視圖,以便視圖中的「滾動」。我想我會通過移動upperView的框架並調整表格視圖的大小(都與滾動偏移量有關)。我得到它幾乎工作如下:滾動調整UITableView的尺寸

- (void)scrollViewDidScroll:(UIScrollView *)scrollView { 

    CGFloat contentOffsetY = scrollView.contentOffset.y; 

    if (contentOffsetY > 0) { 
     CGFloat upperHeight = self.upperView.frame.size.height; 
     CGFloat fullTableHeight = self.view.frame.size.height; 

     CGFloat offsetY = (contentOffsetY < upperHeight)? -scrollView.contentOffset.y : -upperHeight; 

     self.upperView.frame = CGRectMake(0, offsetY, 320, upperHeight); 
     scrollView.frame = CGRectMake(0, upperHeight+offsetY, 320, fullTableHeight-(upperHeight+offsetY)); 
    } 
    NSLog(@"%f", self.upperView.frame.origin.y); 
} 

上視圖的起源從0,0開始。

問題是,在來回拖動一點點之後,我失去了該視圖頂部的幾個像素。它似乎無法讓它的原點y回到零。日誌記錄讀取負值,只有最小的拖動才能達到-1。有沒有人做過這樣的事情?如果你能提供幫助,我們非常感激。

回答

1

聽起來就像您總是在顯示插入視圖時將表視圖滾動到頂部。假設情況如此,有一個更好的方法來做到這一點。

UITableView繼承UIScrollViewcontentInset財產。 contentInset屬性在滾動視圖的每個邊上定義邊框。每個邊框都有自己的厚度,默認爲零。這些邊界隻影響滾動視圖允許用戶滾動內容的距離 - 它們不會隱藏內容!如果您設置的頂部插入大於零,併爲滾動視圖指定一個負Y原點的子視圖,則該子視圖可以在邊框中可見,並將隨滾動視圖內容的其餘部分一起滾動。

因此,我們將表視圖的頂部邊界設置爲下拉式的視線的高度,並添加下拉鑑於與它的起源設定其高度的負表視圖的一個子視圖。這將使它完全適合表格視圖第一行上方的屏幕,並且它將與表格視圖一起滾動。當我們檢測到drop-in視圖已經完全在屏幕外滾動時,我們可以從表視圖中將其刪除,並將表視圖的頂部插入設置回零。

我們需要跟蹤落鑑於當前狀態的實例變量:

typedef enum { 
    DropInViewStateHidden, 
    DropInViewStateAppearing, 
    DropInViewStateVisible 
} DropInViewState; 

@implementation ViewController { 
    DropInViewState _dropInViewState; 
} 

在我的測試項目,我只是用一個按鈕來觸發下拉式的視圖。這裏的動作:

- (IBAction)dropIn { 
    if (_dropInViewState != DropInViewStateHidden) 
     return; 

    CGRect frame = self.dropInView.frame; 
    frame.origin.y = -frame.size.height; 
    self.dropInView.frame = frame; 
    [self.tableView addSubview:self.dropInView]; 

    self.tableView.contentInset = UIEdgeInsetsMake(frame.size.height, 0, 0, 0); 
    [self.tableView setContentOffset:frame.origin animated:YES]; 

    _dropInViewState = DropInViewStateAppearing; 
} 

當表視圖滾動時,我們檢查插入視圖的狀態。如果它處於「可見」狀態並且已經在屏幕外滾動,我們將其隱藏。有一點棘手,因爲當我們使插入視圖可見並將其滾動到屏幕上時,我們可以收到scrollViewDidScroll:消息,這會讓我們認爲插入視圖已隱藏。這就是爲什麼我們從DropInViewStateAppearing狀態開始,當我們知道視圖已經出現時,轉換到DropInViewVisible狀態。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView { 
    switch (_dropInViewState) { 
     case DropInViewStateHidden: 
      break; 
     case DropInViewStateVisible: 
      if (scrollView.contentOffset.y >= 0) { 
       // dropInView has been scrolled off-screen 
       self.tableView.contentInset = UIEdgeInsetsZero; 
       [self.dropInView removeFromSuperview]; 
       _dropInViewState = DropInViewStateHidden; 
       break; 
      } 
     case DropInViewStateAppearing: 
      // When I first add dropInView to tableView and tell tableView 
      // to scroll to reveal dropInView, I may get a bunch of 
      // scrollViewDidScroll: messages with contentOffset.y >= 0. 
      // I don't want those messages to hide dropInView, so I sit in 
      // DropInViewStateAppearing until contentOffset.y goes negative, 
      // which means at least part of dropInView is actually on-screen. 
      if (scrollView.contentOffset.y < 0) 
       _dropInViewState = DropInViewStateVisible; 
      break; 
    } 
} 
+0

我有一個搜索欄和拉到刷新的東西也爭奪頂部嵌入區,所以我仍然在繪圖板,但感謝您的好,徹底的答案。 – danh 2012-03-17 14:49:47

0

想通了:在反彈期間,UITableView沒有徹底地發送didScroll消息。這就是爲什麼我錯過了幾個像素。在反彈期間調整大小會使反彈混亂並停止。在我上面的代碼上的修復允許反彈工作(通過移動,而不是調整表的大小),並確保在反彈期間正確放置上部視圖(當contentOffset.y < = 0時)。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView { 

    CGFloat contentOffsetY = scrollView.contentOffset.y; 

    CGFloat upperHeight = self.upperView.frame.size.height; 
    CGFloat fullTableHeight = self.view.frame.size.height; 

    CGFloat offsetY = (contentOffsetY < upperHeight)? -scrollView.contentOffset.y : -upperHeight; 

    if (contentOffsetY > 0) { 
     self.upperView.frame = CGRectMake(0, offsetY, 320, upperHeight); 
     scrollView.frame = CGRectMake(0, upperHeight+offsetY, 320, fullTableHeight-(upperHeight+offsetY)); 
    } else { 
     self.upperView.frame = CGRectMake(0, 0, 320, upperHeight); 
     scrollView.frame = CGRectMake(0.0, upperHeight, 320, scrollView.frame.size.height); 
    } 
    [super scrollViewDidScroll:scrollView]; 
}