Как запретить смахивание при свайпе recyclerView?
У меня есть recyclerView наполненный сообщениями. При сдвиге влево реализую ответ на сообщение. Но это происходит только при полном смахивании сообщения. Я хочу запретить смахивание, установив только небольшое отклонение влево. Кажется нужно использовать метод converToAbsoluteDirection(), но как это сделать? Большое спасибо за любую помощь.
val simpleCallback = object :
ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean = false
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
val position = viewHolder.bindingAdapterPosition
when (direction) {
ItemTouchHelper.LEFT -> {
binding?.answer?.visibility = View.VISIBLE
}
}
}
override fun convertToAbsoluteDirection(flags: Int, layoutDirection: Int): Int {
return super.convertToAbsoluteDirection(flags, layoutDirection)
}
}
val itemTouchHelper = ItemTouchHelper(simpleCallback)
itemTouchHelper.attachToRecyclerView(binding?.messageList)
}
Ответы (1 шт):
ItemTouchHelper.SimpleCallback сам решает когда произошел свайп, и считает, что и нужно просто дать такой translationX чтобы view на экране просто не было, потому что далее будет наверняка вызван adapter.notifyItemDeleted. А вот если свайпа нет, то потом выполняется обратная анимация. Это реализация swipe2delete.
Чтобы решить задачу, надо от его функционала оставить только сдвиг элемента и обратную анимацию, то есть чтоб определение свайпа, реализованное в колбэке, не сработало никогда, при этом вызывать onSwiped когда надо.
Для этого можно выставить параметры:
@Override
public float getSwipeEscapeVelocity(float defaultValue) {
return 1000.0f; // velocity которая наужна, чтоб был реальный swipe, но velocity всегда будет 1.0 или меньше, поэтому реальный swipe не произойдет
}
@Override
public float getSwipeVelocityThreshold(float defaultValue) {
return 1.0f; // Минимальная velocity, которая повлияет на swipe, в итоге определится это значение как velocity
}
@Override
public float getSwipeThreshold(RecyclerView.ViewHolder viewHolder) {
return 100.0f;// Как можно больше, чтоб не получить реальный swipe - множитель для ширины экрана
}
И тогда onSwiped вызывать самостоятельно в onChildDraw:
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
if (Math.abs(dX) >= 200f) { // Если сдвинули на эту величину, считаем, что swipe произошел
onSwiped(viewHolder, (int) Math.signum(dX) < 0.0 ? ItemTouchHelper.LEFT : ItemTouchHelper.RIGHT);
}
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
ЗЫ можно еще явно добавить viewHolder.itemView.performHapticFeedback в onSwiped
ЗЗЫ в onChildDraw можно не вызывать super если dx больше(меньше) чем дистанция свайпа.
ЗЗЗЫ Еще вариант можно просто написать свою реализацию SimpleCallback'а, который не будет отличаться кроме пары методов...