RecyclerView 项目删除行为异常

RecyclerView item removal behaves aberrantly

我正在使用这个 tutorial 为我的 RecyclerView 构建一个 itemTouchListener。 recyclerview 中充满了比屏幕适合的更多的项目(超过 10 个),因此回收开始行动。 itemtouchHelper 处理上下和左右移动。经过 2 天的努力(将 setStableIds 设置为 true,这会导致上下移动时 viewholder 视图闪烁),我终于得到了更好的行为。我的关键功能代码:

  @Override
    public int getItemCount() {
        return questionlist.size();
    }

    @Override
    public void onViewMoved(int oldPosition, int newPosition) {
        targetqueobj = questionlist.get(oldPosition);

        this.fromPosition = oldPosition;
        this.toPosition = newPosition;
        questionlist.remove(targetqueobj);
        questionlist.add(newPosition, targetqueobj);

        //    targetqueobj.setinturn(toPosition+1);
    }



    @Override
    public void onViewSwiped(final RecyclerView.ViewHolder thisviewholder,final int position, int direction) {
        targetqueobj = questionlist.get(position);
        if (direction == ItemTouchHelper.LEFT){
            // saveqset();
            Intent intent = new Intent(context, QuestionEditActivity.class);
            intent.putExtra("com.logictop.mqapp.QuestionObjParcelable",targetqueobj);
            context.startActivity(intent);
        }
        if (direction == ItemTouchHelper.RIGHT) {
            // DIALOG
            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setMessage(R.string.remove_question);
            builder.setNegativeButton(R.string.No, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface arg0, int arg1) {
             //       thisviewholder.itemView.setAlpha(1);
                    notifyDataSetChanged();
                }
            });

            builder.setPositiveButton(R.string.Yes, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface arg0, int arg1) {
                    questionlist.remove(position);
                    notifyItemRemoved(position);
                    notifyItemRangeChanged(position, getItemCount()-position);
                }
            });
            Dialog dialog = builder.create();
            dialog.setCancelable(false);
            dialog.setCanceledOnTouchOutside(false);
            dialog.show();

        }
    }
    if (direction == ItemTouchHelper.RIGHT) {
        // DIALOG
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setMessage(R.string.remove_question);
        builder.setNegativeButton(R.string.No, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface arg0, int arg1) {
                thisviewholder.itemView.setAlpha(1);
                notifyDataSetChanged();
            }
        });

        builder.setPositiveButton(R.string.Yes, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface arg0, int arg1) {
                questionlist.remove(position);
                notifyItemRemoved(position);
                notifyItemRangeChanged(position, getItemCount()-position);
            }
        });
        Dialog dialog = builder.create();
        dialog.setCancelable(false);
        dialog.setCanceledOnTouchOutside(false);
        dialog.show();

    }
}

问题是这样的。虽然 recyclerview 运行平稳,项目的位置变化非常好,但是当一个项目被滑动时,有时当 recyclerview 向下滚动时另一个项目看起来也被删除了(所以看起来被删除的另一个项目填充相同 "screen" 滚动后在 recyclerview 中的位置)。它不会每次都发生,它主要发生在某些特定位置的视图被滑动时。如果我向上或向下移动邻居视图,"gap" 可以修复。

我已经尝试了我在这里找到的每一个解决方案(notifyDataChanged、notifyItemRangeChanged(每个参数组合)。但是没有什么能让我稳定的行为。在大量的计算器搜索之后,我决定听从 [=13 的建议=] 即使我不想那样做(因为它毕竟消除了拥有 recyclerview 的意义)。但那样的话,就会出现其他问题。您将在下面看到,当大部分视图被滑走时,它们较低的视图不会离开屏幕,即使它们显然有 "left the adapter"(无法将它们滑走)。最后,最后的视图仍然停留。

我已经在一个没有任何外部干扰的全新项目上测试了这两种方式。我试过将 notifyDataChanged() 放在 clearView 的重写函数中。似乎没有任何东西可以提供坚如磐石的稳定回收视图,在某些时候它本身不会出现差距。

现在的问题是:有没有一种方法可以使回收工作的 recyclerview 表现得像它应该表现的那样,或者我应该接受这种情况吗? 非常感谢您的关注!

更新 1---------------------------- 有人告诉我,这个 thisviewholder.itemView.setAlpha(1); 可能存在问题,我将其与相应的覆盖 onChildDraw(整个)一起注释掉,该 onChildDraw 用于在滑动时淡出视图。所以现在没有什么是隐形的。问题依旧。

更新 2---------------------------- 我强制执行了 stableIds(已经执行过一次但没有成功)

@Override
public long getItemId(int position){
    return questionlist.get(position).getquestionid();
}

和适配器构造函数

public QSetEditAdapter(ArrayList<QuestionObj_prcl> questionlist, Context context) {
        this.context = context;
        this.questionlist = questionlist;
        setHasStableIds(true);
    }

问题仍然存在。

更新 3---------------------------- 我最终使用了 different tutorial,现在一切正常。非常感谢!

这样改变你的adapter

我不知道为什么会这样 正是在列表下面的方法中,它保留了你第一次给它的值,并没有更新这个值!!

public void onViewSwiped (int position)

但是解决办法是什么??? 解决方案是使用 -> touchHelper.startSwipe(holder) 方法 例如:

holder.itemView.setOnTouchListener(新View.OnTouchListener(){ 改写 public boolean onTouch (View 视图, MotionEvent 事件) { 如果(event.getAction()==MotionEvent.ACTION_DOWN){ 更新=假; touchHelper.startSwipe(持有人); } return 真; } });

这个方法的作用是重新加载删除的动画和视图 祝你好运