0

我正在尝试在recycleview 中实现“滑动删除”项功能。但是当在snackbar上调用UNDO动作时,被删除的项目无法正确恢复。

这是错误。 https://i.imgur.com/hPfaBQX.png

我试图以onChildDraw不同的方式实现,但它不起作用

@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction, int position) {

// backup of removed item
final String deletedItem = adapter.arrIgnoreNumber.get(viewHolder.getAdapterPosition());
final int deletedIndex = viewHolder.getAdapterPosition();


adapter.removeItem(viewHolder.getAdapterPosition());
// showing snack bar with Undo option
Snackbar snackbar = Snackbar.make(coordinatorLayout, "Removed from the list!", Snackbar.LENGTH_LONG);
snackbar.setAction("UNDO", new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            adapter.restoreItem(deletedItem, deletedIndex);
                        }
                    });
                    snackbar.setActionTextColor(Color.YELLOW);
                    snackbar.show();
                }
}

@Override
public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
Bitmap icon;
            Paint p = new Paint();
            if(actionState == ItemTouchHelper.ACTION_STATE_SWIPE){

                View itemView = viewHolder.itemView;
                float height = (float) itemView.getBottom() - (float) itemView.getTop();
                float width = height / 3;

                if(dX > 0){
                    p.setColor(Color.parseColor("#388E3C"));
                    RectF background = new RectF((float) itemView.getLeft(), (float) itemView.getTop(), dX,(float) itemView.getBottom());
                    c.drawRect(background,p);
                    icon = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_delete);
                    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 {
                    p.setColor(Color.parseColor("#D32F2F"));
                    RectF background = new RectF((float) itemView.getRight() + dX, (float) itemView.getTop(),(float) itemView.getRight(), (float) itemView.getBottom());
                    c.drawRect(background,p);
                    icon = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_delete);
                    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, dX, dY, actionState, isCurrentlyActive);
        }

我希望删除的项目可以在列表中恢复

  • 更新:我提供我的适配器以获取更多详细信息:
@NonNull
        @Override
        public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) {
            LayoutInflater inflater = LayoutInflater.from(parent.getContext());
            View view = inflater.inflate(R.layout.list_ignore_item, parent, false);
            return new ViewHolder(view);
        }

@Override
        public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
            final int tmpPos = position;
            viewHolder.phone.setText(arrIgnoreNumber.get(position));
            String name = arrIgnoreNumber.get(position);
            if (!name.isEmpty()) {
                viewHolder.phone.setVisibility(View.VISIBLE);
                viewHolder.name.setText(name);
            } else {
                viewHolder.phone.setVisibility(View.GONE);
                viewHolder.name.setText(arrIgnoreNumber.get(position));
            }
            viewHolder.icon.setImageBitmap(Utils.getBitmapByContactNumber(mContext, arrIgnoreNumber.get(position), false));

@Override
        public long getItemId(int position) {
            return position;
        }

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

        public void removeItem(int position) {
            arrIgnoreNumber.remove(position);
            notifyItemRemoved(position);
        }

        public void restoreItem(String item, int position) {
            arrIgnoreNumber.add(position, item);
            notifyItemInserted(position);
        }
4

1 回答 1

0

以下解决方案对我有用。参考https://www.androidhive.info/2017/09/android-recyclerview-swipe-delete-undo-using-itemtouchhelper/

  1. ItemTouchHelper.SimpleCallback 中
@Override
        public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
            return makeMovementFlags(0, ItemTouchHelper.LEFT);
        }

        @Override
        public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
            return false;
        }

        @Override
        public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
            listener.onSwiped(viewHolder, direction, viewHolder.getAdapterPosition());
        }

        @Override
        public void onSelectedChanged(@Nullable RecyclerView.ViewHolder viewHolder, int actionState) {
            if (viewHolder != null) {
                final View foregroundView = ((IgnoreCallAdapter.ViewHolder) viewHolder).foreground;
                getDefaultUIUtil().onSelected(foregroundView);
            }
        }

        @Override
        public void onChildDrawOver(@NonNull Canvas c, @NonNull RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
            final View foregroundView = ((IgnoreCallAdapter.ViewHolder) viewHolder).foreground;
            getDefaultUIUtil().onDrawOver(c, recyclerView, foregroundView, dX, dY,
                    actionState, isCurrentlyActive);
        }

        @Override
        public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
            final View foregroundView = ((IgnoreCallAdapter.ViewHolder) viewHolder).foreground;
            getDefaultUIUtil().onDraw(c, recyclerView, foregroundView, dX, dY,
                    actionState, isCurrentlyActive);
        }

        @Override
        public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
            final View foregroundView = ((IgnoreCallAdapter.ViewHolder) viewHolder).foreground;
            getDefaultUIUtil().clearView(foregroundView);
        }

        @Override
        public float getSwipeThreshold(@NonNull RecyclerView.ViewHolder viewHolder) {
            return 0.7f;
        }

        @Override
        public int convertToAbsoluteDirection(int flags, int layoutDirection) {
            return super.convertToAbsoluteDirection(flags, layoutDirection);
        }
  1. 项目布局 xml中:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="@dimen/row_view_height_ignore_list"
    android:focusable="true"
    android:foreground="?android:attr/selectableItemBackground"
    android:orientation="vertical">

    <RelativeLayout
        android:id="@+id/ignore_item_background"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/ignore_item_bg">
    </RelativeLayout>


    <LinearLayout
        android:id="@+id/ignore_item_foreground"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/bg_ignore_item_foreground"
        android:orientation="horizontal"
        android:visibility="visible">
        </LinearLayout>

    </LinearLayout>

</FrameLayout>
于 2019-07-25T07:50:36.867 回答