J'ai un adaptateur qui personnalise un recyclerView
et je souhaite ouvrir un menu contextuel sur un événement de clic long sur les éléments de recyclerView
. Comment puis-je faire ceci?
Cela a déjà été répondu ici . Quoi qu'il en soit, vous pouvez le faire comme ceci:
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
private Article article;
private TextView nameTextView;
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
nameTextView = (TextView) itemView.findViewById(R.id.grid_item_article_name_textView);
}
public void bind(Article article) {
this.article = article;
nameTextView.setText(article.getName());
}
@Override
public void onClick(View view) {
// Context context = view.getContext();
// article.getName()
}
@Override
public boolean onLongClick(View view) {
// Handle long click
// Return true to indicate the click was handled
return true;
}
}
Mise à jour: si vous utilisez Kotlin , faites:
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
View.OnClickListener, View.OnLongClickListener {
init {
itemView.setOnClickListener(this)
itemView.setOnLongClickListener(this)
}
private lateinit var article: Article
private val titleTextView: TextView = itemView.findViewById(R.id.item_article_title_textView)
fun bind(article: Article) {
this.article = article
titleTextView.text = article.title
}
override fun onClick(view: View) {
listener.onItemClick(article)
}
override fun onLongClick(view: View): Boolean {
Toast.makeText(view.context, "long click", Toast.LENGTH_SHORT).show()
// Return true to indicate the click was handled
return true
}
}
Vous devez d’abord enregistrer votre activité pour écouter les événements longClick de la recyclerView
(vous n’aurez donc pas à utiliser aucune sorte de onLongClickListener
...):
registerForContextMenu(recyclerView);
Ensuite, vous créez une ressource de menu (context_menu.xml):
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:title="Mostra documento" Android:id="@+id/context_menu_documents_fragment_view"></item>
<item Android:title="Aggiungi ad un contenitore" Android:id="@+id/context_menu_documents_fragment_add_to_box"></item>
<item Android:title="Elimina documento" Android:id="@+id/context_menu_documents_fragment_delete"></item>
</menu>
Dans l'activité où vous vous êtes inscrit pour le menu contextuel, vous substituez ces méthodes:
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
// Inflate Menu from xml resource
MenuInflater menuInflater = getActivity().getMenuInflater();
menuInflater.inflate(R.menu.context_menu_documents_fragment, menu);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
Toast.makeText(getActivity(), " User selected something ", Toast.LENGTH_LONG).show();
return false;
}
Ceci est très important, vous devez modifier le code dans votre adaptateur RecyclerView
comme ceci:
@Override
public void onBindViewHolder(final DocumentViewHolder viewHolder, int position) {
...
viewHolder.itemView.setLongClickable(true);
...
}
Vous êtes maintenant en mesure d'afficher un menu contextuel et d'intercepter la sélection de l'utilisateur! Mais vous ne pouvez pas savoir sur quel élément l'utilisateur a cliqué. Pour ce faire, vous devez utiliser un RecyclerView personnalisé comme celui-ci (code original de Renaud Cerrato):
public class ContextMenuRecyclerView extends RecyclerView {
private RecyclerContextMenuInfo mContextMenuInfo;
public ContextMenuRecyclerView(Context context) {
super(context);
}
public ContextMenuRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ContextMenuRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected ContextMenu.ContextMenuInfo getContextMenuInfo() {
return mContextMenuInfo;
}
@Override
public boolean showContextMenuForChild(View originalView) {
final int longPressPosition = getChildAdapterPosition(originalView);
if (longPressPosition >= 0) {
final long longPressId = getAdapter().getItemId(longPressPosition);
mContextMenuInfo = new RecyclerContextMenuInfo(longPressPosition, longPressId);
return super.showContextMenuForChild(originalView);
}
return false;
}
public static class RecyclerContextMenuInfo implements ContextMenu.ContextMenuInfo {
public RecyclerContextMenuInfo(int position, long id) {
this.position = position;
this.id = id;
}
final public int position;
final public long id;
}
}
Dans la précédente méthode onContextItemSelected()
, vous pouvez connaître l'id et la position de l'item recyclerView
à l'aide de ce code:
ContextMenuRecyclerView.RecyclerContextMenuInfo info = (ContextMenuRecyclerView.RecyclerContextMenuInfo) item.getMenuInfo();
Enfin, vous devez modifier la méthode getItemId () dans votre adaptateur recyclerView et le fichier de présentation pour vous assurer que vous utilisez votre recyclerView et non le Android!
J'ai fait de cette façon:
static class ViewHolder extends RecyclerView.ViewHolder {
TextView tvName;
ViewHolder(View v) {
super(v);
tvName = (TextView) v.findViewById(R.id.textView_Username);
//Single Tapup
v.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(v.getContext(), "Position is " + getAdapterPosition(), Toast.LENGTH_SHORT).show();
}
});
//Long Press
v.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
Toast.makeText(v.getContext(), "Position is " + getAdapterPosition(), Toast.LENGTH_SHORT).show();
return false;
}
});
}
}
J'avais du mal à trouver la position d'objet sur click, cela a fonctionné pour moi:
public void onClick(View view) {
ViewHolder holder =(ViewHolder)view.getTag();
int position = holder.getLayoutPosition();
Log.d("testing ","pos" +position);
}