撤消后 Recyclerview 项目不可见
Recycleview item is not visible after undo
我是 android 编程的新手,在我的应用程序中,我使用 recycleview 来显示 SQLite 数据库的内容,我正在将数据库读入 Arraylist,我在 recycleview 中显示。我已经成功地实现了向左滑动(删除项目)和向右滑动(编辑项目)功能。
我在向左滑动时遇到问题,意味着删除功能,我实现了撤消功能:
void restoreItem( SequenceItem sequenceItem, int position) {
sequenceItemList.add(position, sequenceItem);
notifyItemInserted(position);
notifyItemRangeChanged(position, getItemCount());
}
(SequenceItem 是我的自定义项 class,sequenceItemList 是我的数组列表)
如果我删除第一个或最后一个项目之间的列表项并撤消它们,此功能效果很好。如果我在撤消后删除 recycleview 中的第一个或最后一个项目,我会在该位置看到空白 space,列表项布局绝对不可见,它只是白色。
然后我在调用恢复方法后添加了一个"recycleview.scrollToPosition":
recycleAdapter.restoreItem(deletedItem, deletedIndex);
recyclerView.scrollToPosition(deletedIndex);
此更改后,如果我从回收视图中删除第一项而不是单击撤消,则之前删除的项目会正确恢复,但如果我从回收视图中删除最后一项并单击撤消,我仍然看到空白(白色)项目。
请问是什么问题?
如果您需要更多详细信息,我可以 post 更多代码或详细介绍该应用程序。
编辑于 06.10.2018
我附上了 RecyclerItemTouchHelper class,因为在我看来,这是导致问题的原因:
public class RecyclerItemTouchHelper extends ItemTouchHelper.SimpleCallback {
private RecyclerItemTouchHelperListener listener;
private Context mContext;
public RecyclerItemTouchHelper(Context mContext, int dragDirs, int swipeDirs, RecyclerItemTouchHelperListener listener) {
super(dragDirs, swipeDirs);
this.listener = listener;
this.mContext = mContext;
}
//This is not used
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder viewHolder1) {
return false;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
if (listener != null) {
listener.onSwiped(viewHolder, direction, viewHolder.getAdapterPosition());
}
}
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
View list_foreground = ((RecycleAdapter.mViewHolder)viewHolder).list_foreground;
getDefaultUIUtil().clearView(list_foreground);
}
@Override
public int convertToAbsoluteDirection(int flags, int layoutDirection) {
return super.convertToAbsoluteDirection(flags, layoutDirection);
}
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
if (viewHolder != null) {
View list_foreground = ((RecycleAdapter.mViewHolder)viewHolder).list_foreground;
getDefaultUIUtil().onSelected(list_foreground);
}
}
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
float mdX = dX / 1;
if(actionState == ItemTouchHelper.ACTION_STATE_SWIPE){
Bitmap icon;
Paint p = new Paint();
Resources resources = mContext.getResources();
View itemView = viewHolder.itemView;
float height = (float) itemView.getBottom() - (float) itemView.getTop();
float width = height / 3;
if(dX > 0){ //Swipe right
p.setColor(Color.parseColor("#D32F2F"));
RectF background = new RectF((float) itemView.getLeft() , (float) itemView.getTop(), mdX, (float) itemView.getBottom());
c.drawRect(background,p);
icon = BitmapFactory.decodeResource(resources, R.drawable.ic_delete_white);
RectF icon_dest = new RectF((float) itemView.getLeft() + width ,(float) itemView.getTop() + width,(float) itemView.getLeft()+ 2*width,(float)itemView.getBottom() - width);
c.drawBitmap(icon,null,icon_dest,p);
} else { //Swipe left
p.setColor(Color.parseColor("#388E3C"));
RectF background = new RectF((float) itemView.getRight() + mdX, (float) itemView.getTop(), (float) itemView.getRight(), (float) itemView.getBottom());
c.drawRect(background,p);
icon = BitmapFactory.decodeResource(resources, R.drawable.ic_edit_white);
RectF icon_dest = new RectF((float) itemView.getRight() - 2*width ,(float) itemView.getTop() + width,(float) itemView.getRight() - width,(float)itemView.getBottom() - width);
c.drawBitmap(icon,null,icon_dest,p);
}
}
super.onChildDraw(c, recyclerView, viewHolder, mdX, dY, actionState, isCurrentlyActive);
}
@Override
public void onChildDrawOver(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
View list_foreground = ((RecycleAdapter.mViewHolder)viewHolder).list_foreground;
getDefaultUIUtil().onDrawOver(c, recyclerView, list_foreground, dX, dY, actionState, isCurrentlyActive);
}
}
这里是滑动的 activity 实现:
@Override
public void onSwiped(final RecyclerView.ViewHolder viewHolder, int direction, final int position) {
//Swipe LEFT to DELETE
if (direction == ItemTouchHelper.RIGHT) {
Snackbar snackbar = Snackbar.make(rootLayout, "Phase " + (position + 1) + " is removed!", Snackbar.LENGTH_LONG);
//Backup of removed item dor UNDO purpose
final SequenceItem deletedItem = sequenceItemList.get(viewHolder.getAdapterPosition());
final int deletedIndex = viewHolder.getAdapterPosition();
//Remove the item from recyclerview
recycleAdapter.removeItem(viewHolder.getAdapterPosition());
snackbar.setAction(R.string.undo, new OnClickListener() {
@Override
public void onClick(View v) {
//Restore deleted item
recycleAdapter.restoreItem(deletedItem, deletedIndex);
recyclerView.scrollToPosition(deletedIndex);
}
}).addCallback(new Snackbar.Callback() {
@Override
public void onDismissed(Snackbar snackbar, int dismissType) {
super.onDismissed(snackbar, dismissType);
if (dismissType != DISMISS_EVENT_ACTION) {
//Delete the item from the database
databaseHelper.removePhase(deletedItem);
Toast.makeText(getApplicationContext(), R.string.phase_successfully_deleted, Toast.LENGTH_LONG).show();
}
}
});
snackbar.setActionTextColor(getResources().getColor(R.color.warningColor));
snackbar.show();
}
//Swipe RIGHT to EDIT
else {
Intent intent = new Intent(this, AddPhaseActivity.class);
intent.putExtra("dbPosition", (long) viewHolder.itemView.getTag());
intent.putExtra("rvPosition", position);
recycleAdapter.notifyItemChanged(position);
this.startActivity(intent);
}
}
你的代码没问题。
这种奇怪的表现唯一可能的地方是下面的功能。
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
View list_foreground = ((RecycleAdapter.mViewHolder)viewHolder).list_foreground; getDefaultUIUtil().clearView(list_foreground);
}
你清除错误的观点。尝试清除项目的根视图,例如
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
View itemView= ((RecycleAdapter.mViewHolder)viewHolder).itemView; getDefaultUIUtil().clearView(itemView);
}
或
改变你的
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive)
方法。
放
View list_foreground = ((RecycleAdapter.mViewHolder)viewHolder).list_foreground;
getDefaultUIUtil().onDraw(c, recyclerView, list_foreground, dX, dY,
actionState, isCurrentlyActive);
而不是
super.onChildDraw(c, recyclerView, viewHolder, mdX, dY, actionState, isCurrentlyActive);
它将解决您的问题。
解释:
问题的根源是 onChildDraw
方法调用
super.onChildDraw(c, recyclerView, viewHolder, mdX, dY, actionState, isCurrentlyActive);
它调用
onDraw(Canvas c, RecyclerView recyclerView, View view,
float dX, float dY, int actionState, boolean isCurrentlyActive)
函数内部传递 viewHolder.itemView
作为 view
的参数并像
一样实现对它的翻译
view.setTranslationX(dX);
view.setTranslationY(dY);
但是清晰的视图就像
@Override
public void clearView(View view) {
view.setTranslationX(0f);
view.setTranslationY(0f);
}
所以在你的例子中,函数 onChildDraw
和 clearView
使用不同的视图。
我是 android 编程的新手,在我的应用程序中,我使用 recycleview 来显示 SQLite 数据库的内容,我正在将数据库读入 Arraylist,我在 recycleview 中显示。我已经成功地实现了向左滑动(删除项目)和向右滑动(编辑项目)功能。 我在向左滑动时遇到问题,意味着删除功能,我实现了撤消功能:
void restoreItem( SequenceItem sequenceItem, int position) {
sequenceItemList.add(position, sequenceItem);
notifyItemInserted(position);
notifyItemRangeChanged(position, getItemCount());
}
(SequenceItem 是我的自定义项 class,sequenceItemList 是我的数组列表)
如果我删除第一个或最后一个项目之间的列表项并撤消它们,此功能效果很好。如果我在撤消后删除 recycleview 中的第一个或最后一个项目,我会在该位置看到空白 space,列表项布局绝对不可见,它只是白色。 然后我在调用恢复方法后添加了一个"recycleview.scrollToPosition":
recycleAdapter.restoreItem(deletedItem, deletedIndex);
recyclerView.scrollToPosition(deletedIndex);
此更改后,如果我从回收视图中删除第一项而不是单击撤消,则之前删除的项目会正确恢复,但如果我从回收视图中删除最后一项并单击撤消,我仍然看到空白(白色)项目。
请问是什么问题? 如果您需要更多详细信息,我可以 post 更多代码或详细介绍该应用程序。
编辑于 06.10.2018 我附上了 RecyclerItemTouchHelper class,因为在我看来,这是导致问题的原因:
public class RecyclerItemTouchHelper extends ItemTouchHelper.SimpleCallback {
private RecyclerItemTouchHelperListener listener;
private Context mContext;
public RecyclerItemTouchHelper(Context mContext, int dragDirs, int swipeDirs, RecyclerItemTouchHelperListener listener) {
super(dragDirs, swipeDirs);
this.listener = listener;
this.mContext = mContext;
}
//This is not used
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder viewHolder1) {
return false;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
if (listener != null) {
listener.onSwiped(viewHolder, direction, viewHolder.getAdapterPosition());
}
}
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
View list_foreground = ((RecycleAdapter.mViewHolder)viewHolder).list_foreground;
getDefaultUIUtil().clearView(list_foreground);
}
@Override
public int convertToAbsoluteDirection(int flags, int layoutDirection) {
return super.convertToAbsoluteDirection(flags, layoutDirection);
}
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
if (viewHolder != null) {
View list_foreground = ((RecycleAdapter.mViewHolder)viewHolder).list_foreground;
getDefaultUIUtil().onSelected(list_foreground);
}
}
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
float mdX = dX / 1;
if(actionState == ItemTouchHelper.ACTION_STATE_SWIPE){
Bitmap icon;
Paint p = new Paint();
Resources resources = mContext.getResources();
View itemView = viewHolder.itemView;
float height = (float) itemView.getBottom() - (float) itemView.getTop();
float width = height / 3;
if(dX > 0){ //Swipe right
p.setColor(Color.parseColor("#D32F2F"));
RectF background = new RectF((float) itemView.getLeft() , (float) itemView.getTop(), mdX, (float) itemView.getBottom());
c.drawRect(background,p);
icon = BitmapFactory.decodeResource(resources, R.drawable.ic_delete_white);
RectF icon_dest = new RectF((float) itemView.getLeft() + width ,(float) itemView.getTop() + width,(float) itemView.getLeft()+ 2*width,(float)itemView.getBottom() - width);
c.drawBitmap(icon,null,icon_dest,p);
} else { //Swipe left
p.setColor(Color.parseColor("#388E3C"));
RectF background = new RectF((float) itemView.getRight() + mdX, (float) itemView.getTop(), (float) itemView.getRight(), (float) itemView.getBottom());
c.drawRect(background,p);
icon = BitmapFactory.decodeResource(resources, R.drawable.ic_edit_white);
RectF icon_dest = new RectF((float) itemView.getRight() - 2*width ,(float) itemView.getTop() + width,(float) itemView.getRight() - width,(float)itemView.getBottom() - width);
c.drawBitmap(icon,null,icon_dest,p);
}
}
super.onChildDraw(c, recyclerView, viewHolder, mdX, dY, actionState, isCurrentlyActive);
}
@Override
public void onChildDrawOver(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
View list_foreground = ((RecycleAdapter.mViewHolder)viewHolder).list_foreground;
getDefaultUIUtil().onDrawOver(c, recyclerView, list_foreground, dX, dY, actionState, isCurrentlyActive);
}
}
这里是滑动的 activity 实现:
@Override
public void onSwiped(final RecyclerView.ViewHolder viewHolder, int direction, final int position) {
//Swipe LEFT to DELETE
if (direction == ItemTouchHelper.RIGHT) {
Snackbar snackbar = Snackbar.make(rootLayout, "Phase " + (position + 1) + " is removed!", Snackbar.LENGTH_LONG);
//Backup of removed item dor UNDO purpose
final SequenceItem deletedItem = sequenceItemList.get(viewHolder.getAdapterPosition());
final int deletedIndex = viewHolder.getAdapterPosition();
//Remove the item from recyclerview
recycleAdapter.removeItem(viewHolder.getAdapterPosition());
snackbar.setAction(R.string.undo, new OnClickListener() {
@Override
public void onClick(View v) {
//Restore deleted item
recycleAdapter.restoreItem(deletedItem, deletedIndex);
recyclerView.scrollToPosition(deletedIndex);
}
}).addCallback(new Snackbar.Callback() {
@Override
public void onDismissed(Snackbar snackbar, int dismissType) {
super.onDismissed(snackbar, dismissType);
if (dismissType != DISMISS_EVENT_ACTION) {
//Delete the item from the database
databaseHelper.removePhase(deletedItem);
Toast.makeText(getApplicationContext(), R.string.phase_successfully_deleted, Toast.LENGTH_LONG).show();
}
}
});
snackbar.setActionTextColor(getResources().getColor(R.color.warningColor));
snackbar.show();
}
//Swipe RIGHT to EDIT
else {
Intent intent = new Intent(this, AddPhaseActivity.class);
intent.putExtra("dbPosition", (long) viewHolder.itemView.getTag());
intent.putExtra("rvPosition", position);
recycleAdapter.notifyItemChanged(position);
this.startActivity(intent);
}
}
你的代码没问题。 这种奇怪的表现唯一可能的地方是下面的功能。
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
View list_foreground = ((RecycleAdapter.mViewHolder)viewHolder).list_foreground; getDefaultUIUtil().clearView(list_foreground);
}
你清除错误的观点。尝试清除项目的根视图,例如
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
View itemView= ((RecycleAdapter.mViewHolder)viewHolder).itemView; getDefaultUIUtil().clearView(itemView);
}
或
改变你的
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive)
方法。
放
View list_foreground = ((RecycleAdapter.mViewHolder)viewHolder).list_foreground;
getDefaultUIUtil().onDraw(c, recyclerView, list_foreground, dX, dY,
actionState, isCurrentlyActive);
而不是
super.onChildDraw(c, recyclerView, viewHolder, mdX, dY, actionState, isCurrentlyActive);
它将解决您的问题。
解释:
问题的根源是 onChildDraw
方法调用
super.onChildDraw(c, recyclerView, viewHolder, mdX, dY, actionState, isCurrentlyActive);
它调用
onDraw(Canvas c, RecyclerView recyclerView, View view,
float dX, float dY, int actionState, boolean isCurrentlyActive)
函数内部传递 viewHolder.itemView
作为 view
的参数并像
view.setTranslationX(dX);
view.setTranslationY(dY);
但是清晰的视图就像
@Override
public void clearView(View view) {
view.setTranslationX(0f);
view.setTranslationY(0f);
}
所以在你的例子中,函数 onChildDraw
和 clearView
使用不同的视图。