如何在 RecyclerView 中使用 AnimatedStateListDrawable
How to use AnimatedStateListDrawable inside a RecyclerView
我正在尝试创建一个 RecyclerView
任务列表,状态为 done 和 undone,我想在这些状态之间创建一个漂亮的过渡。
所以我创建了一个 animated-selector
来在状态之间进行转换,但是当我在 RecyclerView
中使用它时,转换不起作用,当我在 [=60= 上测试它时] 在 RecyclerView
之外它可以正常工作。
Screen with the RecyclerView
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>
我在适配器项 onClickListener
中切换 Task
的属性 isDone
并将 animated-selector
设置为 [=23] 的 android:src
=] 我的 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
我调用 notifyDataSetChanged()
当 liveData allTasks 改变时,在 TaskViewHolder
绑定我更新AppCompatImageView
选中状态。
TaskAdapter.kt
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()
}
}
我认为问题出在我更改 Task 对象的状态时调用的 notifyDataSetChanged()
,因为我想象 RecyclerView
突然更新布局并且不显示过渡状态动画,但如果我不调用 notifyDataSetChanged()
,RecyclerView
将不会更改列表项状态。
如果有人遇到与我相同的情况,请做出回应。
在 notifyDataSetChanged()
方法文档中:
RecyclerView will attempt to synthesize visible structural change
events for adapters that report that they have {@link #hasStableIds()
stable IDs} when this method is used. This can help for the purposes
of animation and visual object persistence but individual item views
will still need to be rebound and relaid out.
所以我将 hasStableIds()
设置为我的 Adapter
并且成功了!
val taskAdapter = TaskAdapter(this, taskViewModel)
taskAdapter.setHasStableIds(true)
我正在尝试创建一个 RecyclerView
任务列表,状态为 done 和 undone,我想在这些状态之间创建一个漂亮的过渡。
所以我创建了一个 animated-selector
来在状态之间进行转换,但是当我在 RecyclerView
中使用它时,转换不起作用,当我在 [=60= 上测试它时] 在 RecyclerView
之外它可以正常工作。
Screen with the RecyclerView
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>
我在适配器项 onClickListener
中切换 Task
的属性 isDone
并将 animated-selector
设置为 [=23] 的 android:src
=] 我的 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
我调用 notifyDataSetChanged()
当 liveData allTasks 改变时,在 TaskViewHolder
绑定我更新AppCompatImageView
选中状态。
TaskAdapter.kt
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()
}
}
我认为问题出在我更改 Task 对象的状态时调用的 notifyDataSetChanged()
,因为我想象 RecyclerView
突然更新布局并且不显示过渡状态动画,但如果我不调用 notifyDataSetChanged()
,RecyclerView
将不会更改列表项状态。
如果有人遇到与我相同的情况,请做出回应。
在 notifyDataSetChanged()
方法文档中:
RecyclerView will attempt to synthesize visible structural change events for adapters that report that they have {@link #hasStableIds() stable IDs} when this method is used. This can help for the purposes of animation and visual object persistence but individual item views will still need to be rebound and relaid out.
所以我将 hasStableIds()
设置为我的 Adapter
并且成功了!
val taskAdapter = TaskAdapter(this, taskViewModel)
taskAdapter.setHasStableIds(true)