如何在 RecyclerView 中使用 AnimatedStateListDrawable aslv_status.xmlitem_task.xmlTaskViewModel.kt任务适配器.kt

问题描述

我正在尝试制作具有 doneundone 状态的任务列表的 RecyclerView,我想在这些状态之间创建一个漂亮的过渡。

所以我创建了一个 animated-selector 来在状态之间进行转换,但是当我在 RecyclerView 内部使用它时转换不起作用,当我在 RecyclerView 外部的 Button/ImageView 上测试它时{1}} 正常工作。

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>

我切换了适配器项 isDoneTask属性 onClickListener,并将 animated-selector 设置为 android:srcAppCompatimageView我的 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)
}

TaskAdapterinit 上,当 liveData allTask​​s 发生变化时,我调用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() 会突然更新布局并且不显示过渡状态动画,但是如果我不会调用 RecyclerViewnotifyDataSetChanged() 不会更改列表项状态。

解决方法

如果有人遇到和我一样的情况,我会做出回应。

notifyDataSetChanged() 方法文档中:

RecyclerView 将尝试合成可见的结构变化 报告它们具有 {@link #hasStableIds() 的适配器的事件 使用此方法时的稳定 ID}。这可以帮助达到目的 动画和视觉对象持久性,但单个项目视图 仍然需要反弹和重新布局。

所以我将 hasStableIds() 设置为我的 Adapter 并且它起作用了!

val taskAdapter = TaskAdapter(this,taskViewModel)
taskAdapter.setHasStableIds(true)