簡體   English   中英

UITableView滾動到底部,與EstimatedRowHeight混淆

[英]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支持UIScrollViewcontentSize 如果估計的大小是錯誤的,則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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM