我有一个RecyclerView,它允许滑动删除功能。定义后,将显示Snackbar,以确认删除操作,并允许用户“撤消”删除操作。
一切正常,直到我删除位置0的项目,然后按undo
。该项目将重新插入列表,但用户需要向上滚动以使其重新显示。
在RecyclerView上设置recyclerView.isNestedScrollingEnabled"
在协调器布局上使用layoutCoordinator.scrollTo(0, 0)
在RecyclerView上使用recyclerView.smoothScrollToPosition(0)
在RecyclerView上使用recyclerView.scrollToPosition(0)
在RecyclerView上使用recyclerView.scrollTo(0, 0)
在适配器上使用itemAdapter.notifiyItemInserted(0)
在适配器上使用itemAdapter.notifiyItemchanged(0)
在适配器上使用itemAdapter.notifyDataSetChanged()
使用layoutManager.scrollToPositionWithOffset(0, 0)
LayoutManager
创建自定义LayoutManager
并覆盖
smoothScrollToPosotion()
和我自己的实现。
以上均未提供解决方案。
下面是工作原理。
在onCreateView
内部-这是在设置itemAdapter
和recyclerView
:
val itemAdapter = object : ItemRecyclerViewAdapter() {
override fun onItemClicked(item: Item) {
// todo
}
}
val layoutManager = LinearLayoutManager(context)
recyclerView.layoutManager = layoutManager
recyclerView.adapter = itemAdapter
这是我的swipeToDeleteCallback
和Snackbar
动作,用于“撤消”删除操作:
val swipeToDeleteCallback = object : SwipeToDeleteCallback() {
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
val position = viewHolder.adapterPosition
val item = itemAdapter.currentList[position]
viewModel.deleteItem(item)
val snackBar = Snackbar.make(
recyclerView,
getString(R.string.snackbar_msg_deleted_card),
Snackbar.LENGTH_LONG
)
snackBar.setAction(R.string.snack_bar_undo) {
viewModel.restoreItem(item)
recyclerView.smoothScrollToPosition(position)
}
snackBar.show()
}
}
val itemTouchHelper = ItemTouchHelper(swipeToDeleteCallback)
itemTouchHelper.attachToRecyclerView(recyclerView)
设置从ViewModel观察到的LiveData项目。更改将立即传递给适配器:
val items = viewModel.items.await()
items.observe(viewLifecycleOwner, Observer {
it?.let {
itemAdapter.setItems(it)
}
})
使用DiffUtilCallback提交列表:
fun setItems(list: List<Item>?) {
adapterScope.launch {
val itemsList = when(list) {
null -> emptyList()
else -> list.sortedByDescending {
it.itemId
}
}
withContext(Dispatchers.Main) {
submitList(itemsList)
}
}
}
到目前为止,唯一起作用的是我的Snackbar
动作中的这种骇人听闻的解决方案:
snackBar.setAction(R.string.snack_bar_undo) {
viewModel.restoreItem(item)
if (position == 0) {
itemsAdapter.notifyItemInserted(0)
recyclerView.smoothScrollToPosition(0)
}
}
在这里,我正在检查项目position
是否为0
。如果是这样,则告诉适配器在item
处插入了新的position 0
-然后开始滚动。否则,请勿执行任何操作,因为position
以外的0
上的任何项目都将插入并制作动画,因为DiffUtilCallback
。
此临时修复程序有效,但滚动为“快照”,并在日志中产生错误:
RecyclerView:平滑滚动时越过目标位置
此外,此解决方案无法100%地起作用。大约有60%的时间。
有人知道我找不到更好的解决方案/东西以及解决上述错误的方法吗?