You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RecyclerView动画结束后如何正确更新列表项内容?

问题解决:RecyclerView滑动删除后条目显示异常

问题分析

滑动删除前置条目后,屏幕末尾的条目TextView无法正确显示内容,核心原因在于:

  1. RecyclerView复用机制+通知不完整:删除条目后,后续条目的位置发生变更,但仅调用notifyItemRemoved只会触发删除动画,不会通知后续条目重新绑定数据,导致复用的ViewHolder未更新内容。
  2. Swipe绘制逻辑冗余:SwipeToDeleteCallback中重复调用super.onChildDraw,可能导致画布绘制残留,干扰View正常显示。

解决方案

1. 修复适配器的通知逻辑

修改DictionaryAdapter的removeEntry方法,在删除条目后,通知后续所有条目位置更新并重新绑定:

public void removeEntry(int position) {
    entries.remove(position);
    notifyItemRemoved(position);
    // 通知删除位置之后的所有条目重新绑定数据
    notifyItemRangeChanged(position, entries.size() - position);
}

2. 清理Swipe绘制逻辑中的冗余代码

修改SwipeToDeleteCallback的onChildDraw方法,移除重复的super.onChildDraw调用,避免画布绘制异常:

@Override
public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
    View itemView = viewHolder.itemView;
    int itemHeight = itemView.getHeight();

    boolean isCancelled = dX == 0 && !isCurrentlyActive;

    if (isCancelled) {
        clearCanvas(c, itemView.getRight() + dX, (float) itemView.getTop(), (float) itemView.getRight(), (float) itemView.getBottom());
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
        return;
    }

    background.setColor(backgroundColor);
    background.setBounds(itemView.getRight() + (int) dX, itemView.getTop(), itemView.getRight(), itemView.getBottom());
    background.draw(c);

    int deleteIconTop = itemView.getTop() + (itemHeight - intrinsicHeight) / 2;
    int deleteIconMargin = (itemHeight - intrinsicHeight) / 2;
    int deleteIconLeft = itemView.getRight() - deleteIconMargin - intrinsicWidth;
    int deleteIconRight = itemView.getRight() - deleteIconMargin;
    int deleteIconBottom = deleteIconTop + intrinsicHeight;

    deleteDrawable.setBounds(deleteIconLeft, deleteIconTop, deleteIconRight, deleteIconBottom);
    deleteDrawable.draw(c);

    // 仅保留一次父类绘制调用
    super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}

3. 确保ViewHolder绑定位置的准确性

在onBindViewHolder中使用holder.getAdapterPosition()获取最新位置,避免复用导致的位置错位:

@Override
public void onBindViewHolder(DictionaryAdapter.ViewHolder holder, int position) {
    // 获取当前ViewHolder对应的最新adapter位置
    int adapterPosition = holder.getAdapterPosition();
    if (adapterPosition == RecyclerView.NO_POSITION) {
        return;
    }
    Entry entry = entries.get(adapterPosition);

    holder.wordRussianTextView.setText(entry.getWord(Entry.LANGUAGE.RUSSIAN));
    holder.wordHebrewTextView.setText(entry.getWord(Entry.LANGUAGE.HEBREW));
    holder.progressBar.setProgress(entry.getProgress());

    Log.e("onBindViewHolder", "New item:");
    Log.e("onBindViewHolder", "russian : " + holder.wordRussianTextView.getText());
    Log.e("onBindViewHolder", "hebrew : " + holder.wordHebrewTextView.getText());
    Log.e("onBindViewHolder", "--------------------------------");
}

原理说明

  • notifyItemRangeChanged会触发删除位置之后的所有条目重新调用onBindViewHolder,确保复用的ViewHolder更新到正确的数据。
  • 清理冗余的super.onChildDraw调用后,画布绘制逻辑更清晰,避免残留的绘制内容覆盖正常的View显示。
  • 使用getAdapterPosition可以获取ViewHolder当前在Adapter中的真实位置,规避复用场景下的位置参数失效问题。

内容的提问来源于stack exchange,提问作者Serafim Dmitriev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 04:43:10