web-dev-qa-db-fra.com

Obtenir l'élément cliqué et sa position dans RecyclerView

Je remplace ma ListView par RecyclerView, liste indiquant ok, mais j'aimerais savoir comment obtenir l'élément cliqué et sa position, similaire à la méthode OnItemClickListener.onItemClick(AdapterView parent, View v, int position, long id) que nous utilisons dans ListView.

Merci pour les idées!

85
Xcihnegn

Basé sur le lien: Pourquoi RecyclerView n’a-t-il pas onItemClickListener ()? et en quoi RecyclerView est différent de Listview? , et aussi l'idée générale de Duncan, je donne ma solution ici:

  • Définissez une interface RecyclerViewClickListener pour transmettre le message de l'adaptateur à ActivityFragment:

    public interface RecyclerViewClickListener {
        public void recyclerViewListClicked(View v, int position);
    }
    
  • DANS Activity/Fragment, IMPLÉMENTEZ L'INTERFACE ET TRANSMETTEZ ÉGALEMENT AUDITEUR À L'ADAPTATEUR:

    @Override
    public void recyclerViewListClicked(View v, int position){... ...}
    
    //set up adapter and pass clicked listener this
    myAdapter = new MyRecyclerViewAdapter(context, this);
    
  • DANS Adapter ET ViewHolder:

    public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ItemViewHolder> {
       ... ... 
       private Context context;
       private static RecyclerViewClickListener itemListener;
    
    
       public MyRecyclerViewAdapter(Context context, RecyclerViewClickListener itemListener) {
           this.context = context;
           this.itemListener = itemListener;
           ... ...
       }
    
    
       //ViewHolder class implement OnClickListener, 
       //set clicklistener to itemView and, 
       //send message back to Activity/Fragment 
       public static class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
           ... ...
           public ItemViewHolder(View convertView) {
               super(convertView);
               ... ...
               convertView.setOnClickListener(this);
           }
    
           @Override
           public void onClick(View v) {
               itemListener.recyclerViewListClicked(v, this.getPosition());     
    
           }
       }
    }
    

APR&EGRAVE;S AVOIR TEST&EACUTE;, CELA FONCTIONNE BIEN. 


[_/ _ METTRE &AGRAVE; JOUR
]

Depuis l'API 22, RecyclerView.ViewHoler.getPosition() est obsolète, donc getLayoutPosition()

152
Xcihnegn
public class MyRvAdapter extends RecyclerView.Adapter<MyRvAdapter.MyViewHolder>{
    public Context context;
    public ArrayList<RvDataItem> dataItems;

    ...
    constructor
    overrides
    ...

    class MyViewHolder extends RecyclerView.ViewHolder{
        public TextView textView;
        public Context context;

        public MyViewHolder(View itemView, Context context) {
            super(itemView);

            this.context = context;

            this.textView = (TextView)itemView.findViewById(R.id.textView);

            // on item click
            itemView.setOnClickListener(new View.OnClickListener(){
                @Override
                public void onClick(View v) {
                    // get position
                    int pos = getAdapterPosition();

                    // check if item still exists
                    if(pos != RecyclerView.NO_POSITION){
                        RvDataItem clickedDataItem = dataItems.get(pos);
                        Toast.makeText(v.getContext(), "You clicked " + clickedDataItem.getName(), Toast.LENGTH_SHORT).show();
                    }
                }
            });
        }
    }
}
27
Uday Hiwarale

Voici un exemple pour définir un écouteur de clic. 

Adapter extends  RecyclerView.Adapter<MessageAdapter.MessageViewHolder> {  ...  }

 public static class MessageViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        public TextView     tv_msg;
        public TextView     tv_date;
        public TextView     tv_sendTime;
        public ImageView    sharedFile;
        public ProgressBar sendingProgressBar;

        public MessageViewHolder(View v) {
            super(v);
            tv_msg =  (TextView) v.findViewById(R.id.tv_msg);
            tv_date = (TextView)  v.findViewById(R.id.tv_date);
            tv_sendTime = (TextView)  v.findViewById(R.id.tv_sendTime);
            sendingProgressBar = (ProgressBar) v.findViewById(R.id.sendingProgressBar);
            sharedFile = (ImageView) v.findViewById(R.id.sharedFile);

            sharedFile.setOnClickListener(this);

        }

        @Override
        public void onClick(View view) {
        int position  =   getAdapterPosition();


            switch (view.getId()){
                case R.id.sharedFile:


                    Log.w("", "Selected"+position);


                    break;
            }
        }

    }
13
Gilberto Ibarra

Mettez ce code où vous définissez la vue du recycleur en activité.

    rv_list.addOnItemTouchListener(
            new RecyclerItemClickListener(activity, new RecyclerItemClickListener.OnItemClickListener() {
                @Override
                public void onItemClick(View v, int position) {

                    Toast.makeText(activity, "" + position, Toast.LENGTH_SHORT).show();
                }
            })
    );

Ensuite, faites une classe séparée et mettez ce code: 

import Android.content.Context;
import Android.support.v7.widget.RecyclerView;
import Android.view.GestureDetector;
import Android.view.MotionEvent;
import Android.view.View;
public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {

    private OnItemClickListener mListener;
    public interface OnItemClickListener {
        public void onItemClick(View view, int position);
    }
    GestureDetector mGestureDetector;
    public RecyclerItemClickListener(Context context, OnItemClickListener listener) {
        mListener = listener;
        mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                return true;
            }
        });
    }
    @Override
    public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
        View childView = view.findChildViewUnder(e.getX(), e.getY());
        if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
            mListener.onItemClick(childView, view.getChildAdapterPosition(childView));
        }
        return false;
    }

    @Override
    public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) {
    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }
}
10
bhumika rijiya

Si vous voulez un événement Click de recycle-View à partir d'activité/fragment au lieu d'un adaptateur, vous pouvez également utiliser le raccourci suivant.

recyclerView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                final TextView txtStatusChange = (TextView)v.findViewById(R.id.txt_key_status);
                txtStatusChange.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Log.e(TAG, "hello text " + txtStatusChange.getText().toString() + " TAG " + txtStatusChange.getTag().toString());
                        Util.showToast(CampaignLiveActivity.this,"hello");
                    }
                });
                return false;
            }
        });

Vous pouvez également utiliser d’autres méthodes comme l’interface

5
Amandeep Rohila
recyclerViewObject.addOnItemTouchListener(
    new RecyclerItemClickListener(
        getContext(),
        recyclerViewObject,
        new RecyclerItemClickListener.OnItemClickListener() {
            @Override public void onItemClick(View view, int position) {
                // view is the clicked view (the one you wanted
                // position is its position in the adapter
            }
            @Override public void onLongItemClick(View view, int position) {
            }
        }
    )
);
4
Cosmin Badulescu

Utilisez le code ci-dessous: -

public class SergejAdapter extends RecyclerView.Adapter<SergejAdapter.MyViewHolder>{

...

class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{


    @Override
    public void onClick(View v) {
        // here you use position
        int position = getAdapterPosition();
        ...

    }
}
}
2
Akanksha Rathore

RecyclerView ne fournit pas une telle méthode.

Pour gérer les événements de clic sur RecyclerView, j'ai fini par implémenter onClickListener dans mon adaptateur, lors de la liaison du ViewHolder: Dans mon ViewHolder, je garde une référence à la vue racine (comme vous pouvez le faire avec vos ImageViews, TextViews, etc.) et le viewHolder sur lequel j'ai placé une balise avec les informations nécessaires pour gérer les clics (tels que la position) et un clicklistener

1
Zoubiock

créer un fichier Java avec le code ci-dessous 

public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
private OnItemClickListener mListener;

public interface OnItemClickListener {
    public void onItemClick(View view, int position);
}

GestureDetector mGestureDetector;

public RecyclerItemClickListener(Context context, OnItemClickListener listener) {
    mListener = listener;
    mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
        @Override public boolean onSingleTapUp(MotionEvent e) {
            return true;
        }
    });
}

@Override public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
    View childView = view.findChildViewUnder(e.getX(), e.getY());
    if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
        mListener.onItemClick(childView, view.getChildLayoutPosition(childView));
        return true;
    }
    return false;
}

@Override public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { }

@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

}

et utilisez simplement l'écouteur sur votre objet RecyclerView.

recyclerView.addOnItemTouchListener(  
new RecyclerItemClickListener(context, new RecyclerItemClickListener.OnItemClickListener() {
  @Override public void onItemClick(View view, int position) {
    // TODO Handle item click
  }
}));
1
MazRoid

Utilisez getLayoutPosition () dans votre méthode Java d'interface personnalisée. Cela retournera la position sélectionnée d'un article, vérifier tous les détails sur 

https://becody.com/get-clicked-item-and-its-position-in-recyclerview/

0
Rana Aamer

Chaque fois que j'utilise une autre approche. Les personnes semblent stocker ou obtenir une position sur une vue, plutôt que de stocker une référence à un objet affiché par ViewHolder.

J'utilise cette approche à la place, et stockez-la dans ViewHolder lorsque onBindViewHolder () est appelée et définissez référence à null dans onViewRecycled ().

Chaque fois que ViewHolder devient invisible, il est recyclé. Cela n'affecte donc pas la consommation de mémoire importante.

@Override
public void onBindViewHolder(final ItemViewHolder holder, int position) {
    ...
    holder.displayedItem = adapterItemsList.get(i);
    ...
}

@Override
public void onViewRecycled(ItemViewHolder holder) {
    ...
    holder.displayedItem = null;
    ...
}

class ItemViewHolder extends RecyclerView.ViewHolder {
    ...
    MySuperItemObject displayedItem = null;
    ...
}
0
Kirill Volkov

A partir du concepteur, vous pouvez définir la propriété onClick de listItem sur une méthode définie avec un seul paramètre. J'ai un exemple de méthode défini ci-dessous. La méthode getAdapterPosition vous donnera l'index du listItem sélectionné.

public void exampleOnClickMethod(View view){
    myRecyclerView.getChildViewHolder(view).getAdapterPosition());
}

Pour plus d'informations sur la configuration d'un RecyclerView, consultez la documentation ici: https://developer.Android.com/guide/topics/ui/layout/recyclerview

0
Spencer Milner

Voici le moyen le plus simple et le plus facile de trouver la position de l'élément cliqué:

J'ai aussi fait face au même problème. 

Je voulais trouver la position de l'élément cliqué/sélectionné de RecyclerView () et effectuer des opérations spécifiques sur cet élément particulier.

la méthode getAdapterPosition () fonctionne comme un charme pour ce genre de choses. J'ai trouvé cette méthode après une longue journée de recherche et après avoir essayé de nombreuses autres méthodes.

int position = getAdapterPosition();
Toast.makeText(this, "Position is: "+position, Toast.LENGTH_SHORT).show();

Vous n'êtes pas obligé d'utiliser une méthode supplémentaire. Créez simplement une variable globale nommée 'position' et initialisez-la avec getAdapterPosition () dans l'une des méthodes principales de l'adaptateur (classe ou similaire).

Voici une brève documentation de ce link .

getAdapterPosition ajouté dans la version 22.1.0 int getAdapterPosition () Renvoie la position de l'adaptateur de l'élément représenté par ce ViewHolder . Notez que cela peut être différent de getLayoutPosition () s'il y a des mises à jour de l'adaptateur en attente, mais qu'une nouvelle passe de présentation n'a pas encore eu lieu . RecyclerView ne gère aucune mise à jour d’adaptateur jusqu’à la prochaine traversée de la présentation. Cela peut créer des incohérences temporaires entre ce que l'utilisateur voit à l'écran et le contenu de l'adaptateur. Cette incohérence n’est pas importante car elle sera inférieure à 16 ms, mais cela pourrait poser un problème si vous souhaitez utiliser la position ViewHolder pour accéder à l’adaptateur. Parfois, vous aurez peut-être besoin d'obtenir la position exacte de l'adaptateur pour effectuer certaines actions en réponse à des événements utilisateur. Dans ce cas, vous devriez utiliser cette méthode qui calculera la position de l'adaptateur du ViewHolder.

Heureux d'aider. N'hésitez pas à poser des doutes.

0
Himanshu Nimje

Extension courte pour Kotlin
La méthode retourne la position absolue de tous les éléments (pas la position des seuls éléments visibles).

fun RecyclerView.getChildPositionAt(x: Float, y: Float): Int {
    return getChildAdapterPosition(findChildViewUnder(x, y))
}

Et utilisation

val position = recyclerView.getChildPositionAt(event.x, event.y)
0
comm1x
//Create below methods into the Activity which contains RecyclerView.


private void createRecyclerView() {

final RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recyclerView);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    MyAdapter myAdapter=new MyAdapter(dataAray,MianActivity.this);
    recyclerView.setAdapter(myAdapter);
    recyclerView.setItemAnimator(new DefaultItemAnimator());

    setRecyclerViewClickListner(recyclerView);
}

private void setRecyclerViewClickListner(RecyclerView recyclerView){

    final GestureDetector gestureDetector = new GestureDetector(MainActivity.this,new GestureDetector.SimpleOnGestureListener() {
        @Override public boolean onSingleTapUp(MotionEvent e) {
            return true;
        }
    });


    recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
        @Override
        public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {
            View child =recyclerView.findChildViewUnder(motionEvent.getX(),motionEvent.getY());
            if(child!=null && gestureDetector.onTouchEvent(motionEvent)){
               int position=recyclerView.getChildLayoutPosition(child);
                String name=itemArray.get(position).name;

            return true;
        }

        @Override
        public void onTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {

        }

        @Override
        public void onRequestDisallowInterceptTouchEvent(boolean b) {

        }
    });
}
0
Kamran

Essayez de cette façon

Classe d'adaptateur:

 public class ContentAdapter extends RecyclerView.Adapter<ContentAdapter.ViewHolder> {

public interface OnItemClickListener {
    void onItemClick(ContentItem item);
}

private final List<ContentItem> items;
private final OnItemClickListener listener;

public ContentAdapter(List<ContentItem> items, OnItemClickListener listener) {
    this.items = items;
    this.listener = listener;
}

@Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_item, parent, false);
    return new ViewHolder(v);
}

@Override public void onBindViewHolder(ViewHolder holder, int position) {
    holder.bind(items.get(position), listener);
}

@Override public int getItemCount() {
    return items.size();
}

static class ViewHolder extends RecyclerView.ViewHolder {

    private TextView name;
    private ImageView image;

    public ViewHolder(View itemView) {
        super(itemView);
        name = (TextView) itemView.findViewById(R.id.name);
        image = (ImageView) itemView.findViewById(R.id.image);
    }

    public void bind(final ContentItem item, final OnItemClickListener listener) {
        name.setText(item.name);
        itemView.setOnClickListener(new View.OnClickListener() {
            @Override public void onClick(View v) {
                listener.onItemClick(item);
            }
        });
    }
}

}

Dans votre activité ou fragment:

ContentAdapter adapter = new ContentAdapter(itemList, this);

Remarque: implémentez OnItemClickListener en fonction du contexte que vous avez indiqué dans les méthodes activity ou fragment and overide.

0
RajeshVijayakumar