我正在尝试实现RecyclerView
项的自定义更改动画(animateChange
)。
我正在努力解决的问题是,animateChange
不是用oldHolder
和newHolder
的两个不同示例调用的,而是用ViewHolder
的一个(已经更改的)示例调用的(oldHolder
和newHolder
都引用它)。不幸的是,这极大地复杂化了我的动画的实现。
提问
如何配置RecyclerView
(和其他相关组件,如Adapter
,ItemAnimator
,LayoutManager
等),使框架调用animateChange
与2个ViewHolder
示例(一个用于预布局,一个用于后布局)?
我的ItemAnimator
我已经确保canReuseUpdatedViewHolder
返回false
,根据文档,应该在调用animateChange
之前强制创建新的ViewHolder
(或者至少我是这样理解的)。
myRecyclerView.itemAnimator = object : DefaultItemAnimator() {
override fun canReuseUpdatedViewHolder(viewHolder: RecyclerView.ViewHolder) = false
override fun animateChange(
oldHolder: RecyclerView.ViewHolder,
newHolder: RecyclerView.ViewHolder,
preLayoutInfo: ItemHolderInfo,
postLayoutInfo: ItemHolderInfo
): Boolean {
// my anim impl here
// oldHolder === newHolder at time of this method invocation.
// However I'd like oldHolder to reference View in its pre-layout state.
// How to achieve this?
return false
}
}
我的适配器
我已经确保MyAdapter
具有“稳定ID”,并且它正确地覆盖了getItemId(int)
。
myRecyclerView.adapter = MyAdapter() {
init {
hasStableIds(true)
}
fun getItemId(position: Int) = ...
...
}
我还确保:
1.... Adapter
不会覆盖onBindViewHolder
的“有效负载”版本,而是非有效负载版本(onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int)
)。根据some discussions,这也可能会阻止创建新的ViewHolder
示例。
1....在数据更新后,通过notifyDataSetChanged
通知适配器:
open fun setMyData(myData: List<MyDataType>) {
this.myData = myData
notifyDataSetChanged()
}
1.... Adapter.getItemViewType(Int)
在数据更改后保持类型不变。
1条答案
按热度按时间wribegjk1#
我设法解决了这个问题。
有问题的部分是
notifyDataSetChanged
的调用:行为如下:
1.对于
notifyDataSetChanged
,ItemAnimator.animateChange(...)
是通过ViewHolder
的单个(并且已经更新/后期布局)示例调用的。1.但是,调用
notifyItemRangeChanged
而不是notifyDataSetChanged
会导致ItemAnimator.animateChange(...)
被调用,其中包含2个ViewHolder
示例,一个用于预布局(oldHolder
),另一个用于后布局(newHolder
)。最后,我使用DiffUtil为每个列表项正确调用相应的
notify*
方法。