问题描述
我正在尝试制作具有 done 和 undone 状态的任务列表的 RecyclerView
,我想在这些状态之间创建一个漂亮的过渡。
所以我创建了一个 animated-selector
来在状态之间进行转换,但是当我在 RecyclerView
内部使用它时转换不起作用,当我在 RecyclerView
外部的 Button/ImageView 上测试它时{1}} 正常工作。
aslv_status.xml
<?xml version="1.0" encoding="utf-8"?>
<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/done"
android:drawable="@drawable/ic_done"
android:state_selected="true" />
<item
android:id="@+id/undone"
android:drawable="@drawable/ic_undone" />
<transition
android:drawable="@drawable/avd_done_to_undone"
android:fromId="@id/done"
android:toId="@id/undone" />
<transition
android:drawable="@drawable/avd_undone_to_undone"
android:fromId="@id/undone"
android:toId="@id/done" />
</animated-selector>
我切换了适配器项 isDone
中 Task
的属性 onClickListener
,并将 animated-selector
设置为 android:src
的 AppCompatimageView
我的 recyclerView 适配器项目:
item_task.xml
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="@{() -> viewmodel.toggleTaskState(task)}" >
...
<androidx.appcompat.widget.AppCompatimageView
android:id="@+id/imageview_status_image"
android:layout_width="35dp"
android:layout_height="35dp"
android:src="@drawable/aslv_status"
.../>
...
Taskviewmodel.kt
fun toggleTaskState(task: Task) = viewmodelScope.launch {
task.isDone = !task.isDone
taskRepository.updateTask(task)
}
在 TaskAdapter
的 init
上,当 liveData allTasks 发生变化时,我调用了 notifyDataSetChanged()
,并在 TaskViewHolder
绑定上更新了 {{1} } 选中状态。
任务适配器.kt
AppCompatimageView
我认为问题是当我更改 Task 对象的状态时调用了 private var allTasks = viewmodel.allTasks
init {
viewmodel.allTasks.observe(lifecycle,{
notifyDataSetChanged()
})
}
...
class TaskViewHolder(private var binding: ItemTaskBinding,private val viewmodel: Taskviewmodel)
: RecyclerView.ViewHolder(binding.root) {
fun bind(task: Task) {
binding.task = task
binding.viewmodel = viewmodel
binding.imageviewStatusImage.isSelected = task.isDone
binding.executePendingBindings()
}
}
,因为我认为 notifyDataSetChanged()
会突然更新布局并且不显示过渡状态动画,但是如果我不会调用 RecyclerView
,notifyDataSetChanged()
不会更改列表项状态。
解决方法
如果有人遇到和我一样的情况,我会做出回应。
在 notifyDataSetChanged()
方法文档中:
RecyclerView 将尝试合成可见的结构变化 报告它们具有 {@link #hasStableIds() 的适配器的事件 使用此方法时的稳定 ID}。这可以帮助达到目的 动画和视觉对象持久性,但单个项目视图 仍然需要反弹和重新布局。
所以我将 hasStableIds()
设置为我的 Adapter
并且它起作用了!
val taskAdapter = TaskAdapter(this,taskViewModel)
taskAdapter.setHasStableIds(true)