我在我的应用程序中有一个聊天,我希望我的 RV 在新消息到来时保持在位置 0,并且第一个可见项目位置为 0,但是新消息添加在当前可见的消息上方,但可见项目保留在 View ,因此用户必须滚动才能看到新消息。
我的适配器是从 RecyclerView.Adapter<RecyclerView.ViewHolder>
扩展而来的并且我找到了一个小的 hacky 解决方案来让它工作:
private suspend fun update(newItems: List<IChatItem>) {
var recyclerViewState: Parcelable? = null
if ((recyclerView?.layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition() == 0) {
recyclerViewState = recyclerView?.layoutManager?.onSaveInstanceState()
}
val diffResult = withContext(Dispatchers.Default) {
DiffUtil.calculateDiff(Diff(this.currentItems, newItems))
}
diffResult.dispatchUpdatesTo(this)
recyclerViewState?.let {
recyclerView?.layoutManager?.onRestoreInstanceState(recyclerViewState)
}
}
事情是保存 RV 状态,在 DiffUtil 完成它的工作后,恢复它。它确实有效,但现在我正在尝试实现新的适配器并从 ListAdapter
扩展我的适配器类因为它在另一个线程中启动 DiffUtil。它工作得很好,但问题是我不能在这里实现我以前的解决方案,它就是不起作用。
我试过以下:
override fun submitList(list: MutableList<IChatItem>?) {
var recyclerViewState: Parcelable? = null
if ((recyclerView?.layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition() == 0) {
recyclerViewState = recyclerView?.layoutManager?.onSaveInstanceState()
}
super.submitList(list)
recyclerViewState?.let {
recyclerView?.layoutManager?.onRestoreInstanceState(recyclerViewState)
}
}
但这不再有效了。有人有解决办法吗?
PS:我发现了这个问题 - Inserting RecyclerView items at zero position - always stay scrolled to top ,但我认为这不是在适配器列表中添加空的不可见项的最佳解决方案。还有其他想法吗?
UPD:如我所想 - 因为此适配器在另一个线程中启动 DiffUtil,所以它在 DiffUtil 完成其工作之前恢复了 RV 状态。此代码有效:
override fun submitList(list: List<IChatItem>?) {
var recyclerViewState: Parcelable? = null
if ((recyclerView?.layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition() == 0) {
recyclerViewState = recyclerView?.layoutManager?.onSaveInstanceState()
}
super.submitList(list)
recyclerViewState?.let {
Handler().postDelayed(
{
recyclerView?.layoutManager?.onRestoreInstanceState(recyclerViewState)
}, 1000
)
}
}
但这不是我想要的。有什么方法可以检测 DiffUtil 何时完成所有操作?
最佳答案
您可以使用 RecyclerView.AdapterDataObserver() 并处理您需要的内容。
创建实现 RecyclerView.AdapterDataObserver() 的监听器类
并在您的适配器构造函数中调用 registerAdapterDataObserver(您的监听器)
然后处理您的回调。
关于android - RecyclerView - 在 notifiyItemInserted(0) 之后保持在 0 位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54347878/