[英]UITableView scroll to the bottom messed up with EstimatedRowHeight
每當用戶創建新注釋或用戶刷新UITableView時,我都會嘗試滾動到我的UITableView(commentsFeed)的底部。
我使用的代碼是:
func scrollToBottomOfComments() {
var lastRowNumber = commentsFeed.numberOfRowsInSection(0) - 1
var indexPath = NSIndexPath(forRow: lastRowNumber, inSection: 0)
commentsFeed.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: true)
}
問題出在viewDidLoad
:
commentsFeed.rowHeight = UITableViewAutomaticDimension
commentsFeed.estimatedRowHeight = 150
這基本上表明評論可以具有動態高度,因為用戶可以發布非常長的評論或非常簡短的評論。
當我使用estimatedRowHeight時,我的scrollToBottom
沒有正確滾動到底部,因為它基本上假設我的表高度為commentsFeed.count * commentsFeed.estimatedRowHeight
但這不正確。
當我刪除estimatedRowHeight
,它似乎也不起作用,我認為原因是它沒有正確計算行高,因為每行都有動態高度。
我該如何緩解這種情況?
編輯:應該說滾動不會在正確的位置結束,但是當我用手指在任何地方滾動時,數據會跳到應該通過滾動的位置
你為什么不通過類似於下面的方法來計算行的實際大小。
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
CustomObject *message = [list.fetchedObjects objectAtIndex:indexPath.row];
//fontChat not available yet
NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:message];
NSRange all = NSMakeRange(0, text.length);
[text addAttribute:NSFontAttributeName value:[UIFont fontWithName:DEFAULT_FONT size:21] range:all];
[text addAttribute:NSForegroundColorAttributeName value:RGB(61, 61, 61) range:all];
CGSize theSize = [text boundingRectWithSize:CGSizeMake(200, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin context:nil].size;
if (theSize.height == 0) {
theSize.height = FIXED_SIZE;
}
return theSize.height;
}
現在滾動,我使用以下來源:檢查出來。
-(void) scrollTolastRow
{
if (self.tableView.contentSize.height > self.tableView.frame.size.height)
{
CGPoint offset = CGPointMake(0, self.tableView.contentSize.height - self.tableView.frame.size.height);
[self.tableView setContentOffset:offset animated:YES];
}
}
有一些事情可能會影響您的結果,但最有可能的估計身高並不是很好 。 根據我的經驗,任何不太接近真實高度的細胞都會對動畫造成嚴重破壞。 在您的情況下,您提到內容是注釋或自由格式文本。 我猜這些細胞高度變化很大,並且取決於細胞的組成方式,你可能無法提供非常准確的估計,所以你不應該提供。 對於大量的細胞,這會損害性能,但您可能沒有選擇。 相反,您可能希望將注意力轉移到如何將單元格分頁/分頁到表格中以避免代價高昂的計算,或者重新排列單元格以便能夠計算出更好的估算值。 另一個建議可能是使用准確但更簡單的算法來實現estimatedHeightForRowAtIndexPath
來計算高度。 無論如何, 當您支持DynamicType時,estimatedRowHeight的常量值可能永遠不會起作用 。 至少,您需要考慮當前的DynamicType大小。
除此之外,你能做什么? 考慮實現heightForRowAtIndexPath
並計算顯示字符串的高度並緩存結果 (可以使用NSIndexPath -> NSNumber
NSCache
對象),而不是使用UITableViewAutomaticDimension
。 您需要緩存結果,因為沒有estimatedHeight
,加載表時每行調用一次heightForRow
,然后屏幕上顯示的每個單元調用一次。 在iOS 8上使用estimatedHeight
時,在啟動時為每個單元調用一次estimatedHeight
,並在單元格出現時調用heightForRow
。 這是估計至關重要的地方,因為這是用於計算UITableView
支持UIScrollView
的contentSize
。 如果估計的大小是錯誤的,則contentSize
是錯誤的,因此當您要求tableView滾動到最后一個單元格時,最后一個單元格的框架將使用錯誤估計進行計算,從而為您提供不正確的contentOffset
。 不幸的是,我相信 (基於我看到試圖重現你的問題的行為)當你在沒有估計的情況下使用UITableViewAutomaticDimension
時,運行時會隱式估計估計值。
UIKit使用EstimatedRowHeight來估計整個contentSize(和scrollIndicatorInset),因此如果在末尾添加具有自動行維度的新行,則必須在動畫滾動之前將estimatedRowHeight重置為整個tableView的實際平均值。
這不是一個很好的解決方案,因為它更容易計算舊式的行高 - 手動。 或者將新的單元格高度值添加到舊表視圖的內容高度。
但是因為你在表的末尾添加了新行,你可以在中間或頂部位置滾動,最后是底部位置,因為有contentInset.bottom = 0.而且動畫看起來也會更好。
所以:
commentsFeed.scrollToRowAtIndexPath(indexPath, atScrollPosition: .**Middle**, animated: true)
它看起來像.Middle和.Top位置是動畫引擎蓋下的一些條件,它可以防止在底邊和表視圖的內容之間產生差距(+ contentInset.bottom)
PS 為什么不使用手動行高計算?
因為有自動布局,我相信“自動”是自動的快捷方式。 此外,它還可以節省您的時間和麻煩的自定義字體,歸因字符串,組合單元格與更多標簽和其他子視圖等等。
試試這個,對我有用:
NSMutableArray *visibleCellIndexPaths = [[self.tableView indexPathsForVisibleRows] mutableCopy];
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:visibleCellIndexPaths withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
[self.tableView scrollRectToVisible:CGRectMake(0, self.tableView.contentSize.height - self.tableView.bounds.size.height, self.tableView.bounds.size.width, self.tableView.bounds.size.height) animated:YES];
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.