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:
将 hasStableIds() 设置为真。
为您的项目实施 getItemId(int) 和 return 唯一 ID。
我不知道为什么会这样
正是在列表下面的方法中,它保留了你第一次给它的值,并没有更新这个值!!
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 真;
}
});
这个方法的作用是重新加载删除的动画和视图
祝你好运
我正在使用这个 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:
将 hasStableIds() 设置为真。
为您的项目实施 getItemId(int) 和 return 唯一 ID。
我不知道为什么会这样 正是在列表下面的方法中,它保留了你第一次给它的值,并没有更新这个值!!
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 真; } });
这个方法的作用是重新加载删除的动画和视图 祝你好运