6

我構建了一個可變高度自定義表單元的UITableView,它們的高度由包含的多行UILabel的大小決定。我已經連接tableView:heightForRowAtIndexPath:委託方法並使用sizeWithFont:constrainedToSize:正確計算最終高度。UITableViewCell幀高度不匹配tableView:heightForRowAtIndexPath:

我遇到了一個奇怪的問題:在調用數據源方法tableView:cellForRowAtIndexPath:時,正確的每行高度已經按上述方法確定,但單元格的框架與該高度不匹配。相反,單元格的frame.size.height屬性是表視圖的默認單元高度(86像素,因爲我在界面生成器中設置它,正確的高度,當包含的UILabel只有一行文本),而不是tableView:heightForRowAtIndexPath:爲該索引路徑確定的高度。

我使用離隊產生細胞cellForRowAtIndexPath:,就是

// Using storyboards, this never returns nil, no need to check for it 
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:@"SomeIdentifier"]; 
NSLog(@"%f", cell.frame.size.height); // 86, not correct if the cell contains a multi-line UILabel 

那麼看來,無論是iOS的是做幕後,離隊不設置單元格的邊框屬性以匹配計算的高度。這本身並不令人驚訝,它將自己的細胞實例排除在外,而不是它們的幾何形狀。雖然單元格的渲染正確,所以高度屬性設置爲某處,但它發生在cellForRowAtIndexPath:之後。

因此:當我最初填充表格視圖時,cell.frame.size.height對於所有單元格爲86,因爲它們是我向下滾動列表時第一次出現。由於正確的幾何圖形是在顯示每行之前的第一個cellForRowAtIndexPath:之後的某個時間設置的,因此當向後滾動時,對於重新使用後回到視圖中的每個單元格,height屬性都是正確的。

在此之後,我可以隨意滾動表格視圖,高度屬性從該點開始對每個單元保持正確。

在任何基於出隊的重用發生之前,第一次獲得正確的單元高度的正確方法是什麼?我需要這個來重新定位表格單元格的子視圖。我是否需要在cellForRowAtIndexPath:中手動撥打heightForRowAtIndexPath:,然後手動將新創建的CustomCell實例的框架設置爲與該高度相匹配?這似乎是多餘的,我需要創建一種機制來檢測細胞何時以錯誤的框架高度進行檢測,以及何時以正確的框架高度將其排出,以避免這種冗餘。因此,如果有人能夠闡明這背後的邏輯是什麼,我會很感激。

回答

6

正如Flexo所建議的,自己回答這個問題顯然比添加編輯問題更好。所以,這是以前的編輯作爲答案:


沒關係,我應該更好地閱讀文檔。我可以在tableView:willDisplayCell:forRowAtIndexPath:方法UITableViewDelegate中獲得正確的框架,因此這是進行子視圖定製的正確位置,它依賴於正確的框架設置,而不是cellForRowAtIndexPath:

有趣的是,文檔說這一點,雖然:

delegate返回後,表視圖只設置alphaframe屬性,然後只有當動畫行,因爲他們在或滑出。

...因爲調用此委託方法時正確的框架已經存在。但無論如何,問題解決了。

+0

最初的問題確實不錯,但是這個答案不是很好。分享你如何解決問題? – botbot 2014-12-28 10:42:13

0

不要忘記,單元格是UIView,因此覆蓋layoutSubviews也是獲取正確框架並調整子視圖大小/位置的有效方法。只要不要忘記撥打[super layoutSubviews]

0

我發現的最簡單的方法就是在對單元進行任何設置之前調用cell.layoutIfNeeded()。這確保了所有佈局約束條件都被計算出來並且幀被設置。