2015-11-18 17 views
3

問題時endUpdates:當我在UITableView底部(且僅當在底部)和tableView.beginUpdates()/tableView.endUpdates()被調用時,UITableView跳了一點點。我不希望它這樣做。UITableView的跳起來之後開始/使用UITableViewAutomaticDimension

設置:我有UITableViewCells將全部在不同尺寸的一個UITableView,和我使用UITableViewAutomaticDimension大小的細胞。

例: 當我在UITableView的底部,我選擇單元格,隨後調用tableView.beginUpdates()/tableView.endUpdates(),該UITableView滾動/跳起來只是有點。

有沒有人找到一種方法,使其在 tableView.beginUpdates()/tableView.endUpdates()之後沒有任何jump?,而在UITableView的末尾?

對於目前我手動計算我所有的UITableViewCells,我寧願不這樣做,因爲我想利用UITableViewAutomaticDimension

代碼

下面是一些代碼,顯示發生的事情tableView.beginUpdates()之間/ tableView.endUpdates():我的viewWillAppear中

tableView.beginUpdates() 
    cell!.setNeedsUpdateConstraints() 
    cell!.updateConstraintsIfNeeded() 
    cell!.setNeedsLayout() 
    cell!.layoutIfNeeded() 
    tableView.endUpdates() 

public override func viewWillAppear(animated: Bool) { 
    super.viewWillAppear(animated) 

    self.tableView.estimatedRowHeight = 150.0 
    self.tableView.rowHeight = UITableViewAutomaticDimension 


    self.tableView.reloadData() 
    //Bug in 8.0+ forces us to call three extra methods to get dynamic cell heights to work correctly... 
    self.tableView.setNeedsLayout() 
    self.tableView.layoutIfNeeded() 
    self.tableView.reloadData() 
} 

我heightForRow:

public override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { 

    return UITableViewAutomaticDimension 

} 

更新:從tableView.beginUpdates()/tableView.endUpdates()刪除cell!.setNeedsUpdateConstraints()cell!.updateConstraintsIfNeeded()cell!.setNeedsLayout()cell!.layoutIfNeeded()似乎停止了跳動,但後來我的細胞不會進行調整?

編輯:這隻發生時在UITableView底部

+0

我想提一提,我已經目睹了這兩個'的iOS 8'和'的iOS 9'。顯示一些代碼可能是 – Sakiboy

+0

?因爲我使用beginUpdates()/ endUpdates()時從來沒有tableView跳轉,我很好奇它們內部正在做什麼。 –

+0

增加了一些代碼,它是所有非常基本的「通過本書」代碼,雖然... – Sakiboy

回答

0

應該很簡單:

UITableView繼承自UIScrollView。在更新之前,使用UIScrollView的方法獲取當前的滾動偏移量。更新後,將偏移量應用於表格視圖。

就是這樣。

+0

我不知道,這似乎有點hacky ... – Sakiboy

+0

無論如何給它一個嘗試,它只是使跳躍更激烈。 – Sakiboy

0

在玩過這個問題後,它似乎是表視圖本身的一個錯誤。撥打endUpdates會觸發代表func scrollViewDidScroll(_ scrollView: UIScrollView)的代理,該代表報告不正確的內容偏移量。後來重置爲原來的狀態,但第一個不是第二個調用似乎是動畫。

經過進一步的檢查後,這似乎只發生在表視圖向下滾動時,因爲它認爲其整體內容高度不足以使其內容偏移有效。我想這可能是由於內容插入,自動行高和估計的行高。

很難說得清完全錯誤的謊言,但讓我們開始的修復程序:

對於那些使用自動行高速戰速決將極有可能只是增加估計行的高度,無論你期待最大的細胞是。而在大多數情況下,將其增加到一個非常大的價值將不會產生任何問題。

對於其他無法承擔改變估計行高的問題,您可以在進行更新之前通過注入非常大的頁腳視圖來解決問題。看到下面的代碼來獲取圖片(評論應該是對發生的事情的最好解釋)。

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 

     // Modify data source 
     let currentResult = results[indexPath.row] // Fetch object 
     let toggledResult = (object: currentResult.object, extended: !currentResult.extended) // Toggle being extended 
     results[indexPath.row] = toggledResult // Assign it back to array 

     // Find the cell 
     if let cell = tableView.cellForRow(at: indexPath) as? ResultTableViewCell { 
      let currentFooterView = tableView.tableFooterView // Steal the current footer view 
      let newView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: tableView.bounds.width, height: tableView.bounds.height*2.0)) // Create a new footer view with large enough height (Really making sure it is large enough) 
      if let currentFooterView = currentFooterView { 
       // Put the current footer view as a subview to the new one if it exists (this was not really tested) 
       currentFooterView.frame.origin = .zero // Just in case put it to zero 
       newView.addSubview(currentFooterView) // Add as subview 
      } 
      tableView.tableFooterView = newView // Assign a new footer 

      // Doing standard animations 
      UIView.animate(withDuration: 0.3, animations: { 
       cell.resultObject = toggledResult // This will trigger internal cell animations 

       // Standard refresh 
       tableView.beginUpdates() 
       tableView.endUpdates() 
       tableView.tableFooterView = currentFooterView // Put the footer view back 
      }) 
     } 

    } 

對於參考,這是沒有跳修復代碼:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 

     // Modify data source 
     let currentResult = results[indexPath.row] // Fetch object 
     let toggledResult = (object: currentResult.object, extended: !currentResult.extended) // Toggle being extended 
     results[indexPath.row] = toggledResult // Assign it back to array 

     // Find the cell 
     if let cell = tableView.cellForRow(at: indexPath) as? ResultTableViewCell { 
      // Doing standard animations 
      UIView.animate(withDuration: 0.3, animations: { 
       cell.resultObject = toggledResult // This will trigger internal cell animations 

       // Standard refresh 
       tableView.beginUpdates() 
       tableView.endUpdates() 
      }) 
     } 

    } 

注意不要在同一時間兩個補丁的應用。當滾動到底部並且單元格崩潰(調整爲較小的高度)時,估計的高度加上更改的頁腳會導致整個邏輯崩潰。所以,如果你在這一點上有問題,檢查你的估計身高不是太高。

0

其實我找到了一個不錯的方法來解決這個問題。它讓我抓狂,但一看:

所以你

  • 具有可擴展的內容
  • 想表動畫單元格的限制(高例如)
  • ,因此,你叫tableView.beginUpdates()和tableView.endUpdates()

而洙表跳到..

正如其他人之前說的,這是因爲更新的tableView使的tableView滾動

該如何解決?

讓我們假設你的代碼如下所示:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 
     let cell = tableView.cellForRow(at: indexPath) 
     cell.heightConstraint = 100 
     UIView.animate(withDuration: 0.15, animations: { 

      self.view.layoutIfNeeded() 
      self.tableView.beginUpdates() 
      self.tableView.endUpdates() 
     }, completion: nil) 
} 

然後來解決,你必須保存當前的tableView滾動位置,直到()被調用的tableView.endUpdates跳躍問題。

像這樣:

let currentScrollPos : CGFloat? 

override func scrollViewDidScroll(_ scrollView: UIScrollView) { 
     // Force the tableView to stay at scroll position until animation completes 
     if (currentScrollPos != nil){ 
      tableView.setContentOffset(CGPoint(x: 0, y: currentScrollPos!), animated: false) 
     } 
} 
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 
     let cell = tableView.cellForRow(at: indexPath) 
     cell.heightConstraint = 100 
     UIView.animate(withDuration: 0.15, animations: { 

      self.currentScrollPos = self.tableView.contentOffset.y 

      self.view.layoutIfNeeded() 
      self.tableView.beginUpdates() 
      self.tableView.endUpdates() 

      self.currentScrollPos = nil 
     }, completion: nil) 
} 
相關問題