how to set itemTouchHelper swipe selectively?

Viewed 2150

so i have implemented this itemtouchhelper.simple callback on a recyclerview rv.

now in this rv i have set 2 kinds on layout as a row depending on the content type.

so as i set this touchhelper on the rv it is being implemented on both of these layouts even though i did'nt want to do that.i only want to apply that swipe to only one type of this layout.

ItemTouchHelper.SimpleCallback ith = new ItemTouchHelper.SimpleCallback(0,ItemTouchHelper.RIGHT) {
        @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 i) {
            if(viewHolder.itemView.findViewById(R.id.messageholder_from) != null)
            {
                Log.d("texts", "onSwiped: "+viewHolder.itemView.findViewById(R.id.messageholder_from).findViewById(R.id.crfrom));
            }
            adapter.notifyDataSetChanged();
        }
    };
    new ItemTouchHelper(ith).attachToRecyclerView(rv);

as you can see this code i only want to implement the swipe on the row which has this messageholder_from child in it otherwise i don't want to implement the swipe.

is there any way to remove the swipe animation and the listener on this other child messageholder_to.

my app shows either a to_layout or a from_layout depending on he message id.

thanks for any kind of help.

2 Answers

Inside your ItemTouchHelper.SimpleCallback, override the getSwipeDirs() method and return 0 for any row that you want to disable swiping on.

@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    if (viewHolder.itemView.findViewById(R.id.messageholder_from) == null) {
        return 0;
    }

    return super.getSwipeDirs(recyclerView, viewHolder);
}

Depending on exactly how your app is set up, there might be a better way to detect that viewHolder is the kind you want to disallow swiping on. For example, maybe you could have

if (viewHolder instanceof WrongKindOfViewHolder)

or

if (viewHolder.isNotSwipeable)

int makeMovementFlags (int dragFlags,int swipeFlags) is responsible for each row move, swipe or drag.

From documentation :

Convenience method to create movement flags.

For instance, if you want to let your items be drag & dropped vertically and swiped left to be dismissed, you can call this method with: makeMovementFlags(UP | DOWN, LEFT);

Implement getMovementFlags() method and return with makeMovementFlags(0, 0); for which row or viewholder you don't want to add swipe or drag.

Example Code:

@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {

    int dragFlags = 0;
    int swipeFlags = 0;

    if (recyclerView.getLayoutManager().getClass() == LinearLayoutManager.class ) {

        LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
        int orientation = linearLayoutManager.getOrientation();

        if (orientation == LinearLayoutManager.VERTICAL) {

            swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
            dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;


        }else {
            // horizontal
            dragFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
            // no swipe for horizontal layout
            swipeFlags = 0;
        }

    }

    if (viewHolder.getAdapterPosition() == 3) {
         // disable swipe feature for position 3 
        return makeMovementFlags(0, 0);
    }


    return makeMovementFlags(dragFlags, swipeFlags);
}
Related