Android ItemTouchHelper.SimpleCallback get swipe direction
Asked Answered
G

1

7

I have implemented swipe to dismiss into my recyclerview. It triggers 2 functions(editing of the record and deleting). If you swipe to the left, you edit it, if right, you delete it. I have such layout under the general part of the recyclerview item

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#fe5722">

    <ImageView
        android:id="@+id/edit_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_centerVertical="true"
        android:layout_marginStart="24dp"
        android:src="@mipmap/ic_mode_edit_white_24dp" />

    <ImageView
        android:id="@+id/delete_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_centerVertical="true"
        android:layout_marginEnd="24dp"
        android:src="@mipmap/ic_delete_white_24dp" />
</RelativeLayout>

So, if you swipe to the left (delete item) the left icon (for editing) should be hidden till the end of swipe. However, I have no idea how to get the swipe direction in the ItemTouchHelper.SimpleCallback class. Please help.

RecyclerItemTouchHelper.java

public class RecyclerItemTouchHelper extends ItemTouchHelper.SimpleCallback {
private RecyclerItemTouchHelperListener listener;
private ImageView imageView;

public RecyclerItemTouchHelper(int dragDirs, int swipeDirs, RecyclerItemTouchHelperListener listener) {
    super(dragDirs, swipeDirs);
    this.listener = listener;
}

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


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

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

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

@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView,
                        RecyclerView.ViewHolder viewHolder, float dX, float dY,
                        int actionState, boolean isCurrentlyActive) {
    ((PasswordRecyclerViewAdapter.ViewHolder) viewHolder).setEditIconInvisible();
    final View foregroundView = ((PasswordRecyclerViewAdapter.ViewHolder) viewHolder).getLayout();

    getDefaultUIUtil().onDraw(c, recyclerView, foregroundView, dX, dY,
            actionState, isCurrentlyActive);
}

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

    return super.getSwipeDirs(recyclerView, viewHolder);
}

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

@Override
public int convertToAbsoluteDirection(int flags, int layoutDirection) {
    if(layoutDirection == ItemTouchHelper.LEFT){
        Log.d("myLogs", "Налево пошло");
    }
    return super.convertToAbsoluteDirection(flags, layoutDirection);
}

public interface RecyclerItemTouchHelperListener {
    void onSwiped(RecyclerView.ViewHolder viewHolder, int direction, int position);
}

}

Update: I have solved the issue, just updated the onChildDraw method:

@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView,
                        RecyclerView.ViewHolder viewHolder, float dX, float dY,
                        int actionState, boolean isCurrentlyActive) {
    final View foregroundView = ((PasswordRecyclerViewAdapter.ViewHolder) viewHolder).getLayout();
    if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
        if (dX > 0) {
            ((PasswordRecyclerViewAdapter.ViewHolder) viewHolder).getEditIcon().setVisibility(View.VISIBLE);
            ((PasswordRecyclerViewAdapter.ViewHolder) viewHolder).getDeleteIcon().setVisibility(View.GONE);
        } else {
            ((PasswordRecyclerViewAdapter.ViewHolder) viewHolder).getEditIcon().setVisibility(View.GONE);
            ((PasswordRecyclerViewAdapter.ViewHolder) viewHolder).getDeleteIcon().setVisibility(View.VISIBLE);
        }
    }

    getDefaultUIUtil().onDraw(c, recyclerView, foregroundView, dX, dY,
            actionState, isCurrentlyActive);
}
Goyette answered 14/2, 2018 at 20:28 Comment(7)
you have onSwiped() method, dont you?Lorelle
@Lorelle yeah, but it is triggered only when item is completely swipedGoyette
and you want what?Lorelle
I want to hide one of the icons when the swipe gesture is startedGoyette
how do you know if its swipe or move? you would need to predict the future...Lorelle
I have implemented only swipe without drag&drop. I just need to detect the swipe directionGoyette
I do not mind if it is a swipe or just a move. I need to hide one of the icons anywayGoyette
O
6

ItemTouchHelper.Callback has a public method onChildDraw() that will be called on every frame with a dX value. This value is the horizontal translation of the view due to the current swipe action being performed by the user.

You can use the value of dX (and whether it is now positive when it was previously zero or now negative when it was previously zero) to detect whether the user is swiping left-to-right or right-to-left.

private class MyItemTouchCallback extends ItemTouchHelper.Callback {

    private float previousDx = 0;

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        ...
        previousDx = 0;
    }

    @Override
    public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
        if (previousDx <= 0 && dX > 0) {
            // swiping from left to right
        }
        else if (previousDx >= 0 && dX < 0) {
            // swiping from right to left
        }

        ...

        previousDx = dX;
    }
}
Ovenbird answered 14/2, 2018 at 21:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.