androidandroid-recyclerviewswipegestureitemtouchhelper

Dettach SwipeListener from Recyclerview


I've got a simple left/right swipe listener for my RecyclerView, so I created the following function in my fragment.

ItemTouchHelper itemTouchHelper;
public void setDeleteUpdateSwipeListener() {
      ItemTouchHelper.SimpleCallback simpleCallback = new ItemTouchHelper.SimpleCallback(0,
            ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {

        @Override
        public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
            return false;
        }
        @Override
        public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
           //do stuff
           Log.e("i still", "get called");
        }


    };

    itemTouchHelper = new ItemTouchHelper(simpleCallback);
    itemTouchHelper.attachToRecyclerView(rvListDriver);
}

If the user clicks on an item for longer period of time, I don't want to allow any wipes, so I did this in my adapter:

@Override
public void onBindViewHolder(@NonNull DriverListAdapter.ViewHolder holder, int position) {
    final ViewHolder recyclerViewHolder = holder;
    holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
          
            drListFrag.setNoSwipeListener();
            return true;
        }
    });
}

And the corresponding function in my fragment:

public void setNoSwipeListener() {
    itemTouchHelper = new ItemTouchHelper(null);
    itemTouchHelper.attachToRecyclerView(null);
}

However, swipes still are happening and the trace Log.e also gets called. I made sure that the function noSwipe gets called. I also tried other solutions but none of them work for me.

May the issue be cause I don't have the swipelistener in my RecycerViewAddapter but rather in my Fragment/RecycerView object.


Solution

  • You can use a custom ItemTouchHelper.Callback and override isItemViewSwipeEnabled() method.

    The return value of this method determines whether the swipe is enabled or not. If true then it's enabled.

    So, you can have a local boolean field in the customized ItemTouchHelper.Callback with a setter, and toggle its value to false within setNoSwipeListener()

    isItemViewSwipeEnabled() should return this local field

    And when the touch event is over, then reset this boolean to true:

    holder.listItem.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_UP) {
                // Reset the boolean to true
            }
            return false;
        }
    });