Cliquez sur l'article et sa position dans RecyclerView
je remplace mon ListView
par RecyclerView
, liste montrant ok, mais je voudrais savoir comment faire pour obtenir cliqué article 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!
17 réponses
basé sur le lien: pourquoi RecyclerView n'a-t-il pas onItemClickListener()? en quoi RecyclerView diffère-t-elle de Listview? , et aussi l'idée générale de @Duncan, je donne ma solution ici:
-
définissez une interface
RecyclerViewClickListener
pour passer le message de l'adaptateur àActivity
/Fragment
:public interface RecyclerViewClickListener { public void recyclerViewListClicked(View v, int position); }
-
Dans
Activity
/Fragment
mettre en œuvre le interface, et aussi passer l'écouteur à 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
etViewHolder
: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ès les tests, il fonctionne très bien.
[ mise à JOUR ]
depuis API 22, RecyclerView.ViewHoler.getPosition()
est déprécié, donc à la place avec getLayoutPosition()
.
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();
}
}
});
}
}
}
voici un exemple pour définir un clic écouteur.
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;
}
}
}
mettez ce code où vous définissez la vue 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();
}
})
);
alors faire une classe séparée et mettre 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) {
}
}
si vous voulez l'événement de clic de recycle-View de l'activité/fragment au lieu de l'adaptateur, alors vous pouvez également utiliser la voie de raccourci suivante.
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 moyens comme l'utilisation de l'interface
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) {
}
}
)
);
utiliser 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();
...
}
}
}
RecyclerView ne fournit pas une telle méthode.
pour gérer les évènements clics sur RecyclerView, j'ai fini par implémenter onClickListener dans mon adaptateur, en liant le ViewHolder: dans mon ViewHolder je garde une référence à la vue racine (comme vous pouvez le faire avec vos ImageViews, TextViews, etc...) et lors de la fixation du viseur j'ai placé une étiquette sur elle avec des informations dont j'ai besoin pour gérer le clic (comme la position) et un clicklistener
//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) {
}
});
}
d'Essayer cette façon
Classe 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);
Note : implémenter L'OnItemClickListener basé sur le contexte donné par vous dans les méthodes activity ou fragment et overide.
chaque fois que j'utilise une autre approche. Les gens semblent stocker ou obtenir position sur une vue, plutôt que de stocker une référence à un objet qui est affiché par le viseur.
j'utilise cette approche à la place, et je la stocke simplement dans ViewHolder quand onBindViewHolder() est appelé, et fixe la référence à null dans onViewRecycled().
chaque fois que le viseur devient invisible, il est recyclé. Donc cela n'affecte pas la consommation de mémoire.
@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;
...
}
courte extension pour Kotlin 151950920" La méthode retourne la position absolue de tous les items (pas la position des seuls items visibles).
fun RecyclerView.getChildPositionAt(x: Float, y: Float): Int {
return getChildAdapterPosition(findChildViewUnder(x, y))
}
et usage
val position = recyclerView.getChildPositionAt(event.x, event.y)
Voici la façon la plus simple et la plus facile de trouver la position de l'article cliqué:
j'ai aussi fait face au même problème.
je voulais trouver la position de L'article cliqué/sélectionné du RecyclerView() et effectuer quelques opérations spécifiques sur cet article particulier.
méthode getAdapterPosition () fonctionne comme un charme pour ce genre de choses. J'ai trouvé cette méthode après une journée de longue 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'avez pas à utiliser toute méthode supplémentaire. Il suffit de créer une variable globale nommée "position" et de l'initialiser avec getAdapterPosition() dans la méthode principale de l'adaptateur (classe ou similaire).
Voici une brève documentation de ce lien .
getAdapterPosition ajouté dans la version 22.1.0 int getAdapterPosition () Renvoie la position de L'Adaptateur de l'article représenté par ce visualiseur. Notez que ceci pourrait être différent de la position de getlayout() s'il y a des mises à jour d'adaptateur en attente mais qu'un nouveau passage de layout n'a pas encore eu lieu. RecyclerView ne gère aucune mise à jour d'adaptateur jusqu'à la prochaine mise en page transversale. Cela peut créer des incohérences temporaires entre ce que l'utilisateur voit sur l'écran et le contenu de l'adaptateur. Cette incohérence n'a pas d'importance puisqu'elle sera moins mais cela peut poser un problème si vous voulez utiliser la position du viseur pour accéder à l'adaptateur. Parfois, vous pouvez avoir besoin d'obtenir la position exacte de l'adaptateur pour faire certaines actions en réponse aux événements de l'utilisateur. Dans ce cas, vous devez utiliser cette méthode qui calculera la position de L'adaptateur du viseur.
heureux d'aider. N'hésitez pas à demander des doutes.
utilisez getLayoutPosition () dans votre méthode java d'interface personnalisée. Cela retournera la position choisie d'un élément, vérifier tous les détails sur
https://becody.com/get-clicked-item-and-its-position-in-recyclerview /
de la part du concepteur, vous pouvez définir la propriété onClick
du listItem à 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 mise en place D'un RecyclerView, voir la documentation ici: https://developer.android.com/guide/topics/ui/layout/recyclerview
il suffit d'ajouter un élément touch listener sur votre objet RecyclerView.
recyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(context, new RecyclerItemClickListener.OnItemClickListener() {
@Override public void onItemClick(View view, int position) {
// TODO Handle item click
}
}));
dans onViewHolder set onClickListiner à toute vue et dans le clic latéral utiliser ce code:
Toast.makeText (Drawer_bar.cette "position" + position, du pain grillé.LENGTH_SHORT).show ();
remplacer Drawer_Bar
par votre nom D'activité.