【问题标题】:Android Recyclerview Remove Animation Is Applied To All Items Strange BehaviourAndroid Recyclerview Remove Animation 应用于所有项目奇怪的行为
【发布时间】:2026-01-15 09:10:01
【问题描述】:

我正在使用以下库在我的 recyclerview 中为删除项目设置动画 https://github.com/wasabeef/recyclerview-animators

我正在尝试将幻灯片应用于仅删除项目的右侧动画,但由于某种原因,recyclerview 中的所有项目首先消失,然后奇怪地动画回到它们的位置。 请观看以下视频。

这是我的代码,非常简单:

   friends_screen_friendlist_recyclerview.itemAnimator = SlideInRightAnimator()
                   friends_screen_friendlist_recyclerview.itemAnimator?.apply {
                        addDuration = 120;
                       removeDuration = 1000;
                        moveDuration = 500;
                        changeDuration = 500;
                   }
    friendItems.removeAt(0)

               friends_screen_friendlist_recyclerview.adapter!!.notifyItemRemoved(0)

适配器类:

class FriendListAdapter(val items : ArrayList<FriendListItem>, val context: Context,val listener:FriendListListener) : androidx.recyclerview.widget.RecyclerView.Adapter<FriendListViewHolder>(),Filterable {

    var filterItems = ArrayList<FriendListItem>()

    init{
        filterItems = items
    }
    // Gets the number of animals in the list
    override fun getItemCount(): Int {
        return filterItems.size
    }
    override fun getItemViewType(position: Int): Int {
        return position
    }

    override fun getFilter(): Filter {
        return object : Filter() {
            override fun performFiltering(constraint: CharSequence?): FilterResults {
                val charSearch = constraint.toString()
                if (charSearch.isEmpty()) {
                    filterItems = items
                } else {
                    val resultList = ArrayList<FriendListItem>()
                    for (row in items) {
                        if (row.userName.toLowerCase(Locale.ROOT).contains(charSearch.toLowerCase(Locale.ROOT))) {
                            resultList.add(row)
                        }
                    }
                    filterItems = resultList
                }
                val filterResults = FilterResults()
                filterResults.values = filterItems
                return filterResults
            }

            @Suppress("UNCHECKED_CAST")
            override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
                filterItems = results?.values as ArrayList<FriendListItem>
                notifyDataSetChanged()
            }

        }
    }

    // Inflates the item views
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FriendListViewHolder {
        return FriendListViewHolder(LayoutInflater.from(context).inflate(R.layout.friendlist_item, parent, false))
    }

    // Binds each animal in the ArrayList to a view
    override fun onBindViewHolder(holder: FriendListViewHolder, position: Int) {
        //holder?.profileImage?.background = items[position].profileImage
        holder?.userName?.text = filterItems[position].userName
        holder?.level?.text = "Seviye "+filterItems[position].level

        // do the necessary profilePic checks.
        Picasso.get().load(filterItems[position].profileImage).into(holder?.profileImage, object : Callback {
            override fun onSuccess() {
                listener.onProfilePicLoaded()
            }

            override fun onError(e: Exception?) {
                listener.onProfilePicLoaded() // error but anyway. just tell messages class its loaded so it can show the page.

            }
        })


  if(filterItems[position].gender == 0){
            holder?.gender?.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.male_icon))
        }else{
            holder?.gender?.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.female_icon))

        }

        if(filterItems[position].isOnline){
            holder?.isOnline?.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.online_circle))
        }else{
            holder?.isOnline?.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.offline_circle))

        }


        holder.itemContainer.setOnClickListener {
            listener.onFriendSelected(filterItems[position])


        }
        holder.itemContainer.setOnLongClickListener {
            listener.onFriendSelectedAndHolded(filterItems[position],position)
            Log.d("yunusdebug","long")


            return@setOnLongClickListener true

        }


    }


}

class FriendListViewHolder (view: View) : androidx.recyclerview.widget.RecyclerView.ViewHolder(view) {
    // Holds the TextView that will add each animal to
    val itemContainer = view.friendlist_item_container

    val userName = view.friendlist_item_username_textview

    val level = view.friendlist_item_level_textview
    val isOnline = view.friendlist_item_isOnline
    val profileImage = view.friendlist_item_profile_image
    val gender = view.friendlist_item_gender

}

【问题讨论】:

  • 您能否发布您用于配置 RecyclerView 以及 xmls 的所有代码?
  • 我添加了适配器,但我认为它不相关。我将尝试使用干净简单的 recyclerview 和更新。范围一定有问题吗?我认为我的 recyclerview 配置没有任何问题,因为没有动画一切正常。也许它是图书馆的一个错误?
  • 图书馆有 101 个问题 --> github.com/wasabeef/recyclerview-animators/issues @lastpeony4

标签: android android-recyclerview android-animation


【解决方案1】:

当您删除适配器中的项目时,您还应该通知新范围。请尝试以下方法:

friendItems.removeAt(index)
notifyItemRemoved(index)
notifyItemRangeChanged(index,friendItems.size)

【讨论】:

  • 我是否必须在我的适配器类中进行额外的更改才能使其工作?我觉得这无关紧要,因为在库 github 页面文档中没有这样的记录