RecyclerView项目删除行为异常

时间:2017-11-21 21:25:34

标签: android android-recyclerview itemtouchhelper

我正在使用此tutorial为我的RecyclerView构建一个itemTouchListener。 Recyclerview充满了比屏幕更多的物品(超过10个),因此回收利用起了作用。 itemtouchHelper可以处理上下和左右移动。经过2天的挣扎(将setStableIds设为true,导致上下移动时导致视图闪烁),我终于得到了更好的行为。我的关键功能代码:

  @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();

    }
}

问题是这个。虽然回收者视图运行平稳,物品的位置变化非常好,但是当物品被刷掉时,有时候另一件物品也会在向下滚动回收物时被移除(因此看起来被移除的另一物品也会被填满#34;屏幕"滚动后在recyclerview中的位置)。它并不是每次都会发生,它主要发生在一些特定位置的视图被刷掉时。那个"差距"如果我向上或向下移动邻居视图,可以修补。

sorry, you have to wait for a bit to see the thing happening after I remove a view for the second time and scroll down

我已经尝试了我在这里找到的每个解决方案(notifyDataChanged,notifyItemRangeChanged(带有每个参数的组合)。但没有什么能让我得到一个稳定的行为。在很多stackoverflow搜索之后我决定遵循holder.setIsRecyclable(false)的建议 即使我不想这样做(因为它毕竟没有回收者的观点)。但在这种情况下,会出现其他问题。您将在下面看到,当大多数视图被刷掉时,即使它们显然已经离开了适配器,它们也会不会离开屏幕。 (不能把它们擦掉)。最后,最后的观点仍然存在。

you have to wait a bit here as well, in the end you'll see the stuck views

我已经在一个全新的项目中测试了两种方式,没有任何外部的方式。我试过将notifyDataChanged()放在clearView的覆盖函数中。似乎没有任何东西可以提供坚如磐石的稳定回收视图,在某些方面本身不会产生差距。

现在的问题是:有没有办法让循环工作回收的行为像它应该表现或我应该接受这种情况? 非常感谢你的关注!

更新1 ---------------------------- 正如我被告知可能存在这个thisviewholder.itemView.setAlpha(1);的问题,我将它与相应的重写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,现在一切都按预期工作了。非常感谢!

2 个答案:

答案 0 :(得分:0)

以这种方式更改adapter

答案 1 :(得分:-1)

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

public void onViewSwiped(int位置)

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

holder.itemView.setOnTouchListener(新的View.OnTouchListener(){ VerOverride public boolean onTouch(查看视图,MotionEvent事件){ 如果(event.getAction()== MotionEvent.ACTION_DOWN){ 更新=假; touchHelper.startSwipe(持有人); } 返回true; } });

此方法的工作是重新加载已删除的动画和视图 祝你好运