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!
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 à Activity
Fragment
:
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()
.
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 é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;
}
}
}
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) {
}
}
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
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) {
}
}
)
);
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();
...
}
}
}
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
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
}
}));
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/
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;
...
}
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
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.
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)
//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) {
}
});
}
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.