J'essaie d'implémenter un balayage pour ignorer une action dans un RecyclerView, mais lorsque je définis un OnClickListener sur n'importe quelle vue dans un ViewHolder, il remplace tous les événements OnTouch de cette vue.
Je peux abandonner OnClickListener et gérer tous les clics dans TouchListener mais si j'ai plusieurs boutons dans une vue enfant de RecycleView, ce sera beaucoup de code et cela ne ressemble pas à la bonne façon.
Dans mon RecyleView, je configure Swipe pour rejeter les auditeurs ( similaire à ceci ):
setOnTouchListener(touchListener);
setOnScrollListener(touchListener.makeScrollListener());
Cela fonctionne dans le ListView, mais dans le RecycleView le OnClickListener bloque les événements OnTouchListner.
Exemple de mise en page pour la vue 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" />
Gonfler dans 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);
}
Le 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);
}
});
}
J'ai atteint cet objectif en affectant OnClickListener
aux boutons du ViewHolder
et en créant une interface pour les événements tactiles.
L'exemple de projet se trouve sur GitHub: https://github.com/brnunes/SwipeableRecyclerView .
Dans mon cas, chaque élément est un CardView
avec deux boutons, et je veux détecter les événements tactiles dans les CardView
et les Button
s. La disposition CardView
ressemble à ceci:
<?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>
Puis dans le Activity
, j'ai déclaré une interface pour recevoir les événements tactiles:
public interface OnItemTouchListener {
public void onCardViewTap(View view, int position);
public void onButton1Click(View view, int position);
public void onButton2Click(View view, int position);
}
Et dans le ViewHolder
j'affecte OnClickListeners
aux objets que je veux écouter et j'appelle mon écouteur personnalisé:
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());
}
});
}
}
}
Enfin, instanciez le OnItemTouchListener
personnalisé et passez-le au constructeur 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
}