簡體   English   中英

將單元格添加到UITableView的頂部而不會中斷用戶滾動

[英]Adding cells to top of UITableView without interrupting user scrolling

我正在向我的應用程序構建一個簡單的聊天UI,但是在添加單元格時無法滾動。

當用戶在頂部附近滾動時,我觸發了后台加載以獲取其他聊天消息。 當這些到達時,我將它們放在前面(將它們添加到表格視圖的頂部)。

我看到的問題是,當新單元格進入時,表格視圖一直滾動到頂部。

我想要的是,添加新單元格時,用戶的位置和滾動方向/速度不會受到任何干擾。

我已經閱讀了無數有關此問題的文章,並且嘗試了所有建議的解決方案(contentOffset重置,estimatedRowHeight緩存,reloadData,insertRow等),但似乎都無法正常工作。

那里的大多數解決方案都是針對將單元格添加到表視圖底部的情況。 這很好用,因為當您reloadDatacontentOffset不會受到影響。 但是,如果將單元格放在最前面,則無法知道添加的所有新單元格的新總高度。

我應該提到的是,我正在使用具有動態高度的自動調整大小的單元格。 單元格包含的動態文本可能長達多行。

為了消除應用程序其余部分的任何可能的怪癖,我創建了一個簡單的精簡應用程序來說明問題。

您可以在github上進行檢查,並自己嘗試: github.com/nebs/pagination-scroll-test

該應用程序僅模擬了虛假消息的無限列表。 當您一直滾動到頂部時,它將加載並添加更多虛假消息(模擬延遲為2秒)。 所有代碼都在ViewController.swift

您可以忽略大多數樣板代碼。 感興趣的主要部分是reloadTableView()函數的這一行

我擁有的“最佳”(到目前為止)解決方案是嘗試4(請參閱代碼)。 在這里,我只記得最上面呈現的消息,然后再次滾動到該消息。 這樣做是可行的,但是如果用戶處於中間滾動狀態,則會抖動一些,因為它無法精確滾動到用戶所在的位置。

我的代碼中的其他3次嘗試均無效(添加新單元格后,表格視圖跳至頂部)。

我很想知道其他人為此找到了什么解決方案。 這似乎是一個紙面上的瑣碎問題,但是我已經待了很多天了,而且還沒有明確的解決方案。

目前解決此問題的最佳做法是什么? 特別適用於在用戶滾動時頂部(動態,可變高度,自定尺寸)單元格位於頂部的表格視圖。

我預先感謝大家提供的任何提示!

我最終找到了一個效果很好的解決方案。 我將其張貼在這里,以防將來對其他人有所幫助。 仍然對其他答案持開放態度。

基本上,我在視圖框架的頂部找到當前可見的消息,並在頂部找到它的偏移量。 然后,當數據加載時,我再次找到該消息,找到其新的索引路徑,並與偏移量一起滾動到該位置。 這具有將用戶精確地放置到他們所處的位置的效果(從視覺上講,當然,當單元被加載時,從技術上講,用戶在列表中位於更下方)。

我使用此新解決方案發布了對鏈接的github項目的提交(位於“嘗試#5”下,只需取消注釋並注釋掉嘗試1)即可進行測試。)

    var currentMessage: Message? = nil
var offsetFromTopOfMessage: CGFloat = 0
if let topIndexPath = self.tableView.indexPathsForVisibleRows?.first {
    var topMessageRect = self.tableView.rectForRow(at: topIndexPath)
    topMessageRect = topMessageRect.offsetBy(dx: -tableView.contentOffset.x, dy: -tableView.contentOffset.y)
    offsetFromTopOfMessage = topMessageRect.minY
    currentMessage = self.messages[topIndexPath.row]
}
self.generateMoreMessages()
self.tableView.reloadData()
if let targetMessage = currentMessage,
    let targetIndex = (self.messages.index{$0.title == targetMessage.title}) {
    let targetIndexPath = IndexPath(row: targetIndex, section: 0)
    self.tableView.scrollToRow(at: targetIndexPath, at: .top, animated: false)
    self.tableView.contentOffset.y -= offsetFromTopOfMessage
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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