web-dev-qa-db-fra.com

Manipulez l'article long, cliquez sur la vue du recycleur

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?

29
Marco Di Munno

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
    }
}
36
Albert Vila Calvo

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!

11
Mariusz Wiazowski

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;
            }
        });
    }
}
7
Däñish Shärmà

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);
}
2
meera