6

I was able to implement drag and drop items in a list and reorder them. What I need to do is implement a delete functionality where one can select and hold an item and drag it to a trash icon. Once it overlaps the trash icon, the latter will change its color from grey to red. Once the user releases the item, a confirmation modal will appear. enter image description here

From the demo, you can see that dragging the first three items in the list toward the trash icon did not turn the trash icon red but launched the modal. The fourth item did change the trash icon's color, but it was immediately removed from the list without confirmation.

The drag and drop is implemented using ItemTouchHelperCallback:

public class EditItemTouchHelperCallback extends ItemTouchHelper.Callback {

    private final RVAdapter mAdapter;
    private RecyclerView.ViewHolder curHolder;

    private int curPos;
    private boolean deletedSomething;
    private CreatePhotostoryActivity cpa;

    public EditItemTouchHelperCallback(RVAdapter adapter) {
        mAdapter = adapter;
        cpa = new CreatePhotostoryActivity();
    }

    @Override
    public boolean isLongPressDragEnabled() {
        return true;
    }

    @Override
    public boolean isItemViewSwipeEnabled() {
        return false;
    }

    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.START | ItemTouchHelper.END;
        int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
        return makeMovementFlags(dragFlags, swipeFlags);
    }

    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
                          RecyclerView.ViewHolder target) {
        curPos = target.getAdapterPosition();
        if(!deletedSomething){
            mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
        }
        return true;
    }

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

    @Override
    public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        CreatePhotostoryActivity.trashNavbar.setVisibility(View.GONE);
        CreatePhotostoryActivity.navbar.setVisibility(View.VISIBLE);
    }

    @Override
    public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {

        boolean isOver = false;
        deletedSomething = false;

        CreatePhotostoryActivity.trashNavbar.setVisibility(View.VISIBLE);
        CreatePhotostoryActivity.trashNavbar.bringToFront();
        CreatePhotostoryActivity.navbar.setVisibility(View.GONE);

        if(ItemTouchHelper.ACTION_STATE_DRAG == actionState) {
            if (isViewOverlapping(viewHolder.itemView, CreatePhotostoryActivity.trashNavbar)) {
                CreatePhotostoryActivity.trashIcon.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.red500));
                //delete moment
                mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
            } else {
                CreatePhotostoryActivity.trashIcon.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.grey700));
            }

            curHolder=viewHolder;
            curPos = curHolder.getAdapterPosition();
            Log.v("Selected","a viewholder "+ curPos);
        }

        if (isViewOverlapping(curHolder.itemView, CreatePhotostoryActivity.trashNavbar)) {
            isOver = true;
        }

        if(isOver) {
            deletedSomething = true;
            mAdapter.showConfirmationDialogDeleteMoment(curPos);
            Log.v("Dropped","a viewholder "+curHolder);
        }
    }

    private boolean isViewOverlapping(View firstView, View secondView) {
        int[] firstPosition = new int[2];
        int[] secondPosition = new int[2];

        firstView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
        firstView.getLocationOnScreen(firstPosition);
        secondView.getLocationOnScreen(secondPosition);
        int r = firstView.getMeasuredHeight() + firstPosition[1];
        int l = secondPosition[1];
        return r >= l && (r != 0 && l != 0);
    }

}

As you can see it's onSelectedChanged that sets the color of the trash icon and calls the method to launch the confirmation modal. I'm not really sure if I placed the methods in the correct position. In my adapter, I use the following method to delete the item from the list:

@Override
public void onItemDismiss(int position) {
    moments.remove(position);
    notifyItemRemoved(position);
}

The method to launch the confirmation modal calls the above method. It is also located in my adapter:

public void showConfirmationDialogDeleteMoment(final int position) {
    AlertDialog.Builder builder =  new AlertDialog.Builder(createPhotoStoryLayout.getContext(), R.style.AlertDialog);
    builder.setTitle("DO YOU WANT TO DELETE THIS MOMENT?")
            .setPositiveButton("DELETE", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    onItemDismiss(position);
                }
            })
            .setNegativeButton("NO", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    //do nothing
                }
            })
            .setIcon(0);
    AlertDialog alert = builder.create();
    alert.show();
    alert.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT,
            (int) (170 * Resources.getSystem().getDisplayMetrics().density));
    AlertUtils.displayDialog(createPhotoStoryLayout.getContext(), alert, R.drawable.red_500_pill, R.drawable.grey_700_pill, R.color.red500, R.color.grey700);

}

Basically, what I want is something similar to the Android OS, where a user drags the app to the Uninstall icon, changes the icon's color to red, and deletes the app once it's released.

Bargain23
  • 1,504
  • 1
  • 17
  • 40

1 Answers1

0

For developers that still looking for a solution; just an idea, you can try below code. A part of my ItemTouchHelper.Callback implementation. I tried and its working fine in my case.

    interface Callback{
        fun isInDeleteArea(dX: Float, dY: Float): Boolean
    }

    private var removeItem = false


    lateinit var callback: Callback

    override fun onChildDraw(
        c: Canvas,
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder,
        dX: Float,
        dY: Float,
        actionState: Int,
        isCurrentlyActive: Boolean
    ) {
        if (isCurrentlyActive.not() && callback.isInDeleteArea(dX, dY)) {
            removeItem = true
            viewHolder.itemView.isGone = true
            return
        }

        viewHolder.itemView.translationY = dY
        viewHolder.itemView.translationX = dX
    }


    override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {

    }

    override fun getAnimationDuration(
        recyclerView: RecyclerView,
        animationType: Int,
        animateDx: Float,
        animateDy: Float
    ): Long {
        if (removeItem) return 0
        return super.getAnimationDuration(recyclerView, animationType, animateDx, animateDy)
    }


    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}

    override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
        removeItem = false
        super.onSelectedChanged(viewHolder, actionState)
    }
toffor
  • 883
  • 1
  • 7
  • 18
  • Hey! where you able to solve this? also, where did you get that demo from? – Prabh deep Jul 20 '20 at 06:51
  • This code block is from my previous project. I developed it. We had to implement a drag & drop and drag & delete function at the same time. What do you need exactly? – toffor Jul 21 '20 at 17:38
  • Hey, i want to delete item from recycerview with drag and drop functionality. i will thankfull you if provide complete code with same functionality – Prabh deep Jul 22 '20 at 04:42