RecyclerView ItemTouchHelper отменить отменить
Я открываю скрытый вид после смахивания с 2 кнопками "удалить" и "отмена". в моем xml itemrow у меня есть 2 внутренних Relativelayouts
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="10dp"
android:paddingTop="10dp">
<include
android:id="@+id/item_container"
layout="@layout/layout_back" />
<RelativeLayout
android:id="@+id/front"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/quest_background_blue"
android:orientation="horizontal"
android:tag="front"
android:focusableInTouchMode="true">
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_gravity="center_vertical"
android:padding="8dp" />
<include
android:id="@+id/contprice"
style="@style/wrap"
layout="@layout/quest_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true" />
<LinearLayout
style="@style/wrap.linear"
android:layout_gravity="center_vertical"
android:layout_toLeftOf="@id/contprice"
android:layout_toRightOf="@id/icon"
android:layout_weight="0.4">
<TextView
android:id="@+id/title"
style="@style/quest_title"
android:text="Рассказать друзьям" />
<TextView
android:id="@+id/details"
style="@style/quest_detail" />
</LinearLayout>
</RelativeLayout>
</FrameLayout>
RelativeLayout с идентификатором спереди можно перелистывать, на включенном макете с идентификатором item_container, где две кнопки
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:background="@android:color/transparent">
<TextView
android:id="@+id/cancel"
android:textColor="#0eb0a0"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:clickable="true"
android:focusable="false"
android:focusableInTouchMode="false"
android:gravity="center"
android:padding="10dp"
android:text="Отмена"
android:textStyle="bold"/>
<TextView
android:id="@+id/delete"
android:textColor="#e6007e"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:clickable="true"
android:focusable="false"
android:focusableInTouchMode="false"
android:gravity="center"
android:padding="10dp"
android:text="Скрыть"
android:textStyle="bold"/>
</RelativeLayout>
проблема в том что при скрытых раскладках с кнопками показывались кнопки не кликабельные
здесь реализации ItemTouchHelper
public class MyItemTouchHelper extends ItemTouchHelper.SimpleCallback {
private ItemAdapter itemAdapter;
private RecyclerView recyclerView;
public MyItemTouchHelper(RecyclerView mRecyclerView, ItemAdapter itemAdapter) {
super(0, ItemTouchHelper.START | ItemTouchHelper.END);
this.itemAdapter = itemAdapter;
this.recyclerView = mRecyclerView;
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
return makeMovementFlags(0, swipeFlags);
}
@Override
public boolean isItemViewSwipeEnabled() {
return true;
}
@Override
public void onSwiped(final RecyclerView.ViewHolder viewHolder, int direction) {
Log.d("SWIPE", " direction = " + direction);
final ItemAdapter.ItemViewHolder holder = (ItemAdapter.ItemViewHolder) viewHolder;
holder.itemView.setOnClickListener(null);
((ItemAdapter.ItemViewHolder) viewHolder).itemContainer.bringToFront();
((ItemAdapter.ItemViewHolder) viewHolder).itemContainer.invalidate();
((ItemAdapter.ItemViewHolder) viewHolder).itemCancel.setEnabled(true);
((ItemAdapter.ItemViewHolder) viewHolder).itemDelete.setEnabled(true);
((ItemAdapter.ItemViewHolder) viewHolder).itemContainer.setVisibility(View.VISIBLE);
((ItemAdapter.ItemViewHolder) viewHolder).itemDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(v.getContext(), "DELETE " + viewHolder.getAdapterPosition(), Toast.LENGTH_SHORT).show();
itemAdapter.removeItem(viewHolder.getAdapterPosition());
recyclerView.getAdapter().notifyItemRemoved(viewHolder.getAdapterPosition());
}
});
((ItemAdapter.ItemViewHolder) viewHolder).itemCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(v.getContext(), "CANCEL " + viewHolder.getAdapterPosition(), Toast.LENGTH_SHORT).show();
((ItemAdapter.ItemViewHolder) viewHolder).itemContainer.setVisibility(View.INVISIBLE);
holder.itemView.setOnClickListener(ItemAdapter.itemAdapterClickListener(viewHolder.getAdapterPosition()));
recyclerView.getAdapter().notifyItemChanged(viewHolder.getAdapterPosition());
clearView(recyclerView, viewHolder);
((ItemAdapter.ItemViewHolder) viewHolder).itemCancel.setEnabled(false);
((ItemAdapter.ItemViewHolder) viewHolder).itemDelete.setEnabled(false);
((ItemAdapter.ItemViewHolder) viewHolder).itemContext.setVisibility(View.VISIBLE);
((ItemAdapter.ItemViewHolder) viewHolder).itemContext.bringToFront();
((ItemAdapter.ItemViewHolder) viewHolder).itemContext.invalidate();
}
});
}
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
if (viewHolder.getAdapterPosition() == -1) {
return;
}
ItemAdapter.ItemViewHolder holder = (ItemAdapter.ItemViewHolder) viewHolder;
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
if (dX > 0 || dX < 0) {
holder.itemContext.setTranslationX(dX);
}
} else {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY,
actionState, isCurrentlyActive);
}
}
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
View foreground = ((ItemAdapter.ItemViewHolder) viewHolder).getSwipableView();
getDefaultUIUtil().clearView(foreground);
}
}
а вот зритель
public class ItemViewHolder extends RecyclerView.ViewHolder {
TextView itemText;
RelativeLayout itemContainer;
RelativeLayout itemContext;
TextView itemDelete;
TextView itemCancel;
public ItemViewHolder(View itemView) {
super(itemView);
itemText = (TextView) itemView.findViewById(R.id.details);
itemDelete = (TextView) itemView.findViewById(R.id.delete);
itemCancel = (TextView) itemView.findViewById(R.id.cancel);
itemContainer = (RelativeLayout) itemView.findViewById(R.id.item_container);
itemContext = (RelativeLayout) itemView.findViewById(R.id.front);
}
public ViewGroup getSwipableView() {
return itemContext;
}
public ViewGroup getItemContainer() {
return itemContainer;
}
}
если будет более правильное нажатие кнопок, но не с первой попытки UPDATE после пролистывания, затем нажмите на элемент, который по-прежнему находится в режиме пролистывания, и по журналу, который показывает, что первые 3 щелчка являются направлением пролистывания
onSwipe
Log.d("SWIPE", " direction = " + direction);
D/SWIPE: direction = 16
D/SWIPE: direction = 16
D/SWIPE: direction = 16
и после этого нажимает кнопку отмены или удаления
1 ответ
В вашем ItemViewHolder
изменить это
item_container = itemView.findViewById(R.id.item_container);
itemDelete = (TextView) item_container.findViewById(R.id.delete);
itemCancel = (TextView) item_container.findViewById(R.id.cancel);
и добавить
View item_container;
class SwipeItemTouchHelper(private val adapter: QuestsAdapter) : ItemTouchHelper.Callback() {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder) = false
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
adapter.redrawViewHolder(viewHolder.adapterPosition)
}
override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
val swipeView = viewHolder.itemView.findViewById<View>(R.id.front)
return if (swipeView.visibility == View.INVISIBLE) 0
else ItemTouchHelper.Callback.makeMovementFlags(0, ItemTouchHelper.START or ItemTouchHelper.END)
}
override fun onChildDraw(
c: Canvas,
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
dX: Float,
dY: Float,
actionState: Int,
isCurrentlyActive: Boolean
) {
if (viewHolder.adapterPosition == -1) return
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
viewHolder.itemView.findViewById<View>(R.id.front).apply {
ItemTouchHelper.Callback
.getDefaultUIUtil()
.onDraw(c, recyclerView, this, dX, dY, actionState, isCurrentlyActive)
}
}
}
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
super.clearView(recyclerView, viewHolder)
viewHolder.itemView.findViewById<View>(R.id.front).apply {
ItemTouchHelper.Callback.getDefaultUIUtil().clearView(this)
}
}
}
А вот адаптер, например, позвольте мне объяснить, что здесь происходит. 1. После Swipe in itemtouch fun "onSwiped" мы вызываем адаптер fun "redrawViewHolder" 2. В VH у меня есть 2 макета: спереди с некоторыми видами и сзади с кнопками: отменить и удалить 3. В объекте quest у нас есть флаг для смахивания действие "quest.isSwiped = false", здесь true - смахнуть показать backlayout, false - показать нормальный вид VH
Ну, вы можете посмотреть здесь код, он староват, и я его опустил, поэтому его нужно реорганизовать https://github.com/wlTrunks/Swipe_and_delete
class QuestsAdapter(private val quests: MutableList<Quest>) : BaseRecyclerAdapter<RecyclerBaseViewModel<*, *>>() {
fun redrawViewHolder(position: Int) {
if (list[position].model != null) (list[position].model as BackQuest).isSwiped = true
(quests[position] as? BackQuest)?.let {
it.isSwiped = true
notifyItemChanged(position)
}
}
fun onCancelClick(questId: String) {
currentQuest(quests, questId) { index, quest ->
if (list[index].model != null) (list[index].model as BackQuest).isSwiped = false
quest.isSwiped = false
notifyItemChanged(index)
}
}
fun onDeleteClick(questId: String) {
currentQuest(quests, questId) { index, _ ->
list.removeAt(index)
quests.removeAt(index)
notifyItemRemoved(index)
}
}
}