with recyclerview delete and adding android swipe ontouchlistener android-recyclerview

android - delete - Deslice y haga clic en eventos en RecyclerView



swipe menu with recyclerview (1)

Lo OnClickListener asignando OnClickListener para los botones en ViewHolder y creando una interfaz para los eventos táctiles.

El proyecto de muestra está en GitHub: https://github.com/brnunes/SwipeableRecyclerView .

En mi caso, cada elemento es un CardView con dos botones, y quiero detectar los eventos táctiles en CardView y CardView . El diseño de CardView tiene este aspecto:

<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="5dp" android:clickable="true" android:foreground="?android:attr/selectableItemBackground" android:orientation="vertical" card_view:cardCornerRadius="5dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/card_view_title" android:layout_width="match_parent" android:layout_height="50dp" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:gravity="center" android:textColor="@android:color/black" android:textSize="24sp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_below="@id/card_view_title" android:layout_centerHorizontal="true" android:gravity="center"> <Button android:id="@+id/card_view_button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button1" /> <Button android:id="@+id/card_view_button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button2" /> </LinearLayout> </RelativeLayout> </android.support.v7.widget.CardView>

Luego, en la Activity , declaré una interfaz para recibir los eventos táctiles:

public interface OnItemTouchListener { public void onCardViewTap(View view, int position); public void onButton1Click(View view, int position); public void onButton2Click(View view, int position); }

Y en ViewHolder asigno OnClickListeners a los objetos que quiero escuchar y llamo a mi oyente personalizado:

public class CardViewAdapter extends RecyclerView.Adapter<CardViewAdapter.ViewHolder> { private List<String> cards; private OnItemTouchListener onItemTouchListener; public CardViewAdapter(List<String> cards, OnItemTouchListener onItemTouchListener) { this.cards = cards; this.onItemTouchListener = onItemTouchListener; } @Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_view_layout, viewGroup, false); return new ViewHolder(v); } @Override public void onBindViewHolder(ViewHolder viewHolder, int i) { viewHolder.title.setText(cards.get(i)); } @Override public int getItemCount() { return cards == null ? 0 : cards.size(); } public class ViewHolder extends RecyclerView.ViewHolder { private TextView title; private Button button1; private Button button2; public ViewHolder(View itemView) { super(itemView); title = (TextView) itemView.findViewById(R.id.card_view_title); button1 = (Button) itemView.findViewById(R.id.card_view_button1); button2 = (Button) itemView.findViewById(R.id.card_view_button2); button1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onItemTouchListener.onButton1Click(v, getPosition()); } }); button2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onItemTouchListener.onButton2Click(v, getPosition()); } }); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onItemTouchListener.onCardViewTap(v, getPosition()); } }); } } }

Finalmente, OnItemTouchListener una instancia del OnItemTouchListener personalizado y páselo al constructor CardViewAdapter :

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mItems = new ArrayList<>(30); for (int i = 0; i < 30; i++) { mItems.add(String.format("Card number %2d", i)); } OnItemTouchListener itemTouchListener = new OnItemTouchListener() { @Override public void onCardViewTap(View view, int position) { Toast.makeText(MainActivity.this, "Tapped " + mItems.get(position), Toast.LENGTH_SHORT).show(); } @Override public void onButton1Click(View view, int position) { Toast.makeText(MainActivity.this, "Clicked Button1 in " + mItems.get(position), Toast.LENGTH_SHORT).show(); } @Override public void onButton2Click(View view, int position) { Toast.makeText(MainActivity.this, "Clicked Button2 in " + mItems.get(position), Toast.LENGTH_SHORT).show(); } }; mAdapter = new CardViewAdapter(mItems, itemTouchListener); mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); mRecyclerView.setAdapter(mAdapter); // ... Assign the swipe listener }

Estoy tratando de implementar un deslizamiento para descartar la acción en un RecyclerView, pero cuando configuro un OnClickListener en cualquier Vista en un ViewHolder, anula todos los eventos de OnTouch en esa vista.

Puedo abandonar OnClickListener y manejar todos los clics en el TouchListener, pero si tengo varios botones en una vista secundaria de RecycleView será mucho código y esto no parece una buena opción.

En mi RecyleView estoy configurando deslizar para descartar oyentes ( similar a esto ):

setOnTouchListener(touchListener); setOnScrollListener(touchListener.makeScrollListener());

Funciona en ListView, pero en el RecycleView, OnClickListener bloquea los eventos de OnTouchListner.

Ejemplo del diseño de la vista ViewHolder.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/card_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="72dp" android:descendantFocusability="blocksDescendants"> <ImageView android:id="@+id/keep_icon" android:layout_width="48dp" android:layout_height="48dp" android:layout_centerInParent="true" android:src="@drawable/ic_received" />

Inflar en RecyclerView.Adapter:

@Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { View v = mInflater.inflate(R.layout.push_card_view_compat, viewGroup, false); return new ViewHolder(v, onClickListener, onKeepListener); }

The ViewHolder:

public ViewHolder(final View itemView, final OnViewHolderClickListener onClickListener, final OnKeepListener onKeepListener) { super(itemView); keepButton = (ImageView) itemView.findViewById(R.id.keep_icon); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onItemClickListener.onClick(getPosition(), itemView); } }); keepButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onKeepListener.onClick(getPosition(), itemView); } }); }