Quelqu'un utilisant RecyclerView
a-t-il trouvé un moyen de définir une variable onClickListener
pour les éléments de la variable RecyclerView
? est un moyen pour la RecyclerView
d'écouter l'événement onClick
mais je n'arrive pas à le comprendre.
Comme les API ont radicalement changé, il ne me surprendrait pas que vous créiez une OnClickListener
pour chaque élément. Ce n'est pas si compliqué cependant. Dans votre implémentation de RecyclerView.Adapter<MyViewHolder>
, vous devriez avoir:
private final OnClickListener mOnClickListener = new MyOnClickListener();
@Override
public MyViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.myview, parent, false);
view.setOnClickListener(mOnClickListener);
return new MyViewHolder(view);
}
La méthode onClick
:
@Override
public void onClick(final View view) {
int itemPosition = mRecyclerView.getChildLayoutPosition(view);
String item = mList.get(itemPosition);
Toast.makeText(mContext, item, Toast.LENGTH_LONG).show();
}
Voici un moyen mieux et moins étroitement couplé d'implémenter une OnClickListener
pour un RecyclerView
Extrait d'utilisation:
RecyclerView recyclerView = findViewById(R.id.recycler);
recyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(context, recyclerView ,new RecyclerItemClickListener.OnItemClickListener() {
@Override public void onItemClick(View view, int position) {
// do whatever
}
@Override public void onLongItemClick(View view, int position) {
// do whatever
}
})
);
RecyclerItemClickListener
implémentation:
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);
public void onLongItemClick(View view, int position);
}
GestureDetector mGestureDetector;
public RecyclerItemClickListener(Context context, final RecyclerView recyclerView, OnItemClickListener listener) {
mListener = listener;
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
@Override
public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null && mListener != null) {
mListener.onLongItemClick(child, recyclerView.getChildAdapterPosition(child));
}
}
});
}
@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 true;
}
return false;
}
@Override public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { }
@Override
public void onRequestDisallowInterceptTouchEvent (boolean disallowIntercept){}
}
Je le fais de cette manière, sans classes indues, détecteurs, etc. Code simple à l'intérieur de notre adaptateur. Solution spécialement meilleure pour longClick que celle présentée auparavant.
public class PasswordAdapter extends RecyclerView.Adapter<PasswordAdapter.ViewHolder> {
private static ClickListener clickListener;
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
TextView name;
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
name = (TextView) itemView.findViewById(R.id.card_name);
}
@Override
public void onClick(View v) {
clickListener.onItemClick(getAdapterPosition(), v);
}
@Override
public boolean onLongClick(View v) {
clickListener.onItemLongClick(getAdapterPosition(), v);
return false;
}
}
public void setOnItemClickListener(ClickListener clickListener) {
PasswordAdapter.clickListener = clickListener;
}
public interface ClickListener {
void onItemClick(int position, View v);
void onItemLongClick(int position, View v);
}
}
Ensuite, dans un fragment ou une activité, appuyez simplement sur
PasswordAdapter mAdapter = ...;
mAdapter.setOnItemClickListener(new PasswordAdapter.ClickListener() {
@Override
public void onItemClick(int position, View v) {
Log.d(TAG, "onItemClick position: " + position);
}
@Override
public void onItemLongClick(int position, View v) {
Log.d(TAG, "onItemLongClick pos = " + position);
}
});
Découvrez un question@ du commentaire de CommonsWare similaire vers this , qui implémente l'interface OnClickListener
dans la viewHolder
.
Voici un exemple simple de la ViewHolder
:
TextView textView;//declare global with in adapter class
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
textView = (TextView)view.findViewById(Android.R.id.text1);
}
@Override
public void onClick(View view) {
Toast.makeText(view.getContext(), "position = " + getLayoutPosition(), Toast.LENGTH_SHORT).show();
//go through each item if you have few items within recycler view
if(getLayoutPosition()==0){
//Do whatever you want here
}else if(getLayoutPosition()==1){
//Do whatever you want here
}else if(getLayoutPosition()==2){
}else if(getLayoutPosition()==3){
}else if(getLayoutPosition()==4){
}else if(getLayoutPosition()==5){
}
//or you can use For loop if you have long list of items. Use its length or size of the list as
for(int i = 0; i<exampleList.size(); i++){
}
}
}
La Adapter
ressemble alors à ceci:
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view =LayoutInflater.from(parent.getContext()).inflate(Android.R.layout.simple_list_item_1, parent, false);
return new ViewHolder(view);
}
Basé sur la réponse de Jacob Tabak (+1 pour lui), j'ai pu ajouter l'auditeur onLongClick:
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 {
public interface OnItemClickListener {
void onItemClick(View view, int position);
void onItemLongClick(View view, int position);
}
private OnItemClickListener mListener;
private GestureDetector mGestureDetector;
public RecyclerItemClickListener(Context context, final RecyclerView recyclerView, OnItemClickListener listener) {
mListener = listener;
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
@Override
public void onLongPress(MotionEvent e) {
View childView = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (childView != null && mListener != null) {
mListener.onItemLongClick(childView, recyclerView.getChildAdapterPosition(childView));
}
}
});
}
@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) {
}
}
Ensuite, vous pouvez l'utiliser comme ceci:
recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(getActivity(), recyclerView, new RecyclerItemClickListener.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
// ...
}
@Override
public void onItemLongClick(View view, int position) {
// ...
}
}));
C'est ce qui a fonctionné pour moi. Associez la OnClickListener
à la onBindView
. Je ne sais pas vraiment si cela affectera les performances, mais cela semble fonctionner correctement avec peu de code.
public void onBindViewHolder(ViewHolder holder, final int position) {
holder.view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(context, "Recycle Click" + position, Toast.LENGTH_SHORT).show();
}
});
}
C'était si difficile pour moi d'avoir un écouteur d'élément de clic dans l'activité et également d'avoir un écouteur de clic pour une vue unique de l'élément qui ne déclenchera pas cet écouteur. Après avoir joué avec la réponse de Jacob Tabak, je respecte sa réponse car cliquer sur l'élément si aucune autre action tactile dans l'élément n'est présentée.
J'ai une interface personnalisée OnClickListener
qui comporte un événement de clic sur élément qui contient la vue de l'élément sur lequel l'utilisateur a cliqué et la position de l'élément sur l'adaptateur. J'en présente une instance dans le constructeur (ou cela peut être avec setter) et la rattache à l'écouteur de clic du conteneur détenteur de la vue.
J'ai également un autre écouteur de clic dans l'adaptateur (qui peut être dans le détenteur de la vue), qui gérera le clic de vue actuel dans le conteneur.
public class MyRecyclerAdapter extends RecyclerView.Adapter<MyViewHolder> {
private ArrayList<String> mData;
private OnItemClickListener mOnItemClickListener;
public interface OnItemClickListener {
public void onItemClick(View view, int position);
}
public MyRecyclerAdapter(ArrayList<String> itemsData,
OnItemClickListener onItemClickListener) {
mOnItemClickListener = onItemClickListener;
this.mData = itemsData;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View layoutView = LayoutInflater.from(mContext).inflate(
R.layout.list_item, parent, false);
MyViewHolder viewHolder = new MyViewHolder(layoutView);
return viewHolder;
}
@Override
public void onBindViewHolder(MyViewHolder viewHolder,
final int position) {
viewHolder.container.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mOnItemClickListener.onItemClick(v, position);
}
});
viewHilder.button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//do button click work here
}
});
}
@Override
public int getItemCount() {
return mData.size();
}}
Dans l'activité, vous devez initialiser l'adaptateur en transmettant l'instance de la variable OnItemClickListener
.
public class FeedActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
.....
MyRecyclerAdapter adapter = new MyRecyclerAdapter(new ArrayList<String>(), new OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
///list item was clicked
}
});
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(mFeedsAdapter);
}
Et mon ViewHolder
public class MyViewHolder extends RecyclerView.ViewHolder {
public Button button;
public View container;
public MyViewHolder(View itemLayoutView) {
super(itemLayoutView);
container = itemLayoutView;
button = (Button) itemLayoutView.findViewById(R.id.button);
}}
Voici ce dont j'ai eu besoin, au cas où quelqu'un le trouverait utile:
public static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View item) {
super(item);
item.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.d("RecyclerView", "onClick:" + getAdapterPosition());
}
});
}
}
Source: http://blog.csdn.net/jwzhangjie/article/details/36868515
J'ai une bonne solution pour RecyclerView
's onItemClickListener
pour les éléments et les sous-éléments
Étape 1- Créer une interface
public interface OnRecyclerViewItemClickListener
{
/**
* Called when any item with in recyclerview or any item with in item
* clicked
*
* @param position
* The position of the item
* @param id
* The id of the view which is clicked with in the item or
* -1 if the item itself clicked
*/
public void onRecyclerViewItemClicked(int position, int id);
}
Étape 2- Puis utilisez-le dans la méthode onBindViewHolder
de l'adaptateur de la manière suivante
/**
* Custom created method for Setting the item click listener for the items and items with in items
* @param listener OnRecyclerViewItemClickListener
*/
public void setOnItemClickListener(OnRecyclerViewItemClickListener listener)
{
this.listener = listener;
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, final int position)
{
// viewHolder.albumBg.setBackgroundResource(_itemData[position]
// .getImageUrl());
viewHolder.albumName.setText(arrayList.get(position).getName());
viewHolder.artistName.setText(arrayList.get(position).getArtistName());
String imgUrl = arrayList.get(position).getThumbImageUrl();
makeImageRequest(imgUrl, viewHolder);
viewHolder.parentView.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
listener.onRecyclerViewItemClicked(position, -1);
}
});
viewHolder.settingButton.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
listener.onRecyclerViewItemClicked(position, v.getId());
}
});
}
// class to hold a reference to each item of RecyclerView
public static class ViewHolder extends RecyclerView.ViewHolder
{
public TextView albumName, artistName;
public ImageView albumIcon, settingButton;
public LinearLayout parentView;
public ViewHolder(View itemLayoutView)
{
super(itemLayoutView);
// albumBg = (LinearLayout) itemLayoutView
// .findViewById(R.id.albumDlbg);
albumName = (TextView) itemLayoutView.findViewById(R.id.albumName);
artistName = (TextView) itemLayoutView
.findViewById(R.id.artistName);
albumIcon = (ImageView) itemLayoutView.findViewById(R.id.albumIcon);
parentView = (LinearLayout) itemLayoutView
.findViewById(R.id.albumDlbg);
settingButton = (ImageView) itemLayoutView
.findViewById(R.id.settingBtn);
}
}
Étape 3- trouver et configurer la vue du recycleur dans l'activité ou le fragment où vous l'utilisez
recyclerView = (RecyclerView) rootview.findViewById(R.id.vmtopsongs);
lm = new LinearLayoutManager(mActivity);
lm.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(lm);
recyclerView.addItemDecoration(
new HorizontalDividerItemDecoration.Builder(getActivity())
.Paint(Utils.getPaint()).build());
PopularSongsadapter mAdapter = new PopularSongsadapter(gallery,
mActivity, true);
// set adapter
recyclerView.setAdapter(mAdapter);
mAdapter.setOnItemClickListener(this);
// set item animator to DefaultAnimator
recyclerView.setItemAnimator(new DefaultItemAnimator());
Étape 4- Enfin, implémentez l'interface dans l'activité ou le fragment où vous utilisez la vue recyclée
@Override
public void onRecyclerViewItemClicked(int position, int id)
{
if(id==-1){
Toast.makeText(mActivity, "complete item clicked", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(mActivity, "setting button clicked", Toast.LENGTH_LONG).show();
}
}
Voici ce que j'ai fait. Cette solution prend en charge onClick et onLongClick sur les éléments RecyclerView et les vues à l'intérieur des éléments RecyclerView (vues internes).
Je balise viewHolder sur les vues de mon choix:
public RecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_item, null);
ViewHolder viewHolder = new ViewHolder(itemView);
itemView.setOnClickListener( this);
itemView.setOnLongClickListener(this);
viewHolder.imageIV.setOnClickListener(this);
viewHolder.imageIV.setOnLongClickListener(this);
viewHolder.imageIV.setTag(viewHolder);
itemView.setTag(viewHolder);
return viewHolder;
}
Et j'utilise holder.getPosition () pour récupérer la position dans la méthode onClick () (onLongClick est similaire):
public void onClick(View view) {
ViewHolder holder = (ViewHolder) view.getTag();
int position = holder.getPosition();
if (view.getId() == holder.imageIV.getId()){
Toast.makeText(context, "imageIV onClick at" + position, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "RecyclerView Item onClick at " + position, Toast.LENGTH_SHORT).show();
}
}
Une variante avec getChildPosition fonctionne également. Veuillez noter que pour les vues internes, dans onClick (), utilisez:
int position = recyclerView.getChildPosition((View)view.getParent());
Selon moi, l’avantage de cette solution est que, lorsque l’utilisateur clique sur une image, seul l’auditeur d’image onclick () est appelé, alors que lorsque je combine la solution de Jacob pour une vue RecyclerView Item et ma solution pour les vues internes, la vue RecyclerView Item onclick ( ) est également appelé (lorsque vous cliquez sur l'image).
Il existe un moyen beaucoup plus facile de le faire. Il suffit d’appliquer au clic dans onBindViewHolder
sur la vue racine.
Considérez ceci est votre vue pour l'adaptateur,
<LinearLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:card_view="http://schemas.Android.com/apk/res-auto"
Android:id="@+id/linearlayout"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical">
<TextView
Android:id="@+id/textview"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_marginBottom="1dp"
Android:textSize="15sp" />
</LinearLayout>
Puis suivez dans votre adaptateur
//get the layout and make view holder
@Override
public RVAdapter.ViewHolder1 onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_layout, null);
ViewHolder1 viewHolder = new ViewHolder1(view);
return viewHolder;
}
@Override
public void onBindViewHolder(RVAdapter.ViewHolder1 holder, int position) {
//apply on click on your root view
holder.linearlayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Do on click stuff
}
});
}
//make references to views in layout including root view
public class ViewHolder1 extends RecyclerView.ViewHolder {
protected LinearLayout linearlayout = null
protected TextView textview = null;
public CareerLinksViewHolder(View itemView) {
super(itemView);
this.linearlayout = (LinearLayout) itemView.findViewById(R.id.linearlayout);
this.tvCompName = (TextView) itemView.findViewById(R.id.textview);
}
}
Vous pouvez passer de clickListener
à Adapter
.
Dans votre Activity
:
private View.OnClickListener mItemClick = new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = null;
int position = list.getChildPosition(v);
switch (position) {
case 0:
intent = new Intent(MainActivity.this, LeakCanaryActivity.class);
break;
case 1:
intent = new Intent(MainActivity.this, ButterKnifeFragmentActivity.class);
break;
}
if (intent != null) {
MainActivity.this.startActivity(intent);
}
}
};
puis passez-le à Adapter
:
MainAdapter mainAdapter = new MainAdapter(this, mItemClick);
Dans Adapter
's onCreateViewHolder
:
@Override
public MainAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int position) {
View itemView = activity.getLayoutInflater().inflate(R.layout.main_adapter_item, viewGroup, false);
ViewHolder holder = new ViewHolder(itemView);
itemView.setOnClickListener(mItemClick);
return holder;
}
J'ai développé une bibliothèque légère pour Android, vous pouvez visiter https://github.com/ChathuraHettiarachchi/RecycleClick
et suivez pour l'échantillon suivant
RecycleClick.addTo(YOUR_RECYCLEVIEW).setOnItemClickListener(new RecycleClick.OnItemClickListener() {
@Override
public void onItemClicked(RecyclerView recyclerView, int position, View v) {
// YOUR CODE
}
});
Vous pouvez implémenter OnClickListener dans votre classe ViewHolder.
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public Item item
@InjectView(R.id.tv_title)
public TextView tvTitle;
@InjectView(R.id.rl_row)
public RelativeLayout rlRow;
public ViewHolder(View v) {
super(v);
ButterKnife.inject(this, v);
v.setOnClickListener(this);
}
@Override
public void onClick(View view) {
Log.e("item title",item.getTitle());
}
}
Et onBindViewHolder définir l'élément de votre détenteur de vue
public void onBindViewHolder(ViewHolder holder, int position) {
holder.tvTitle.setText(objects.get(position).getTitle());
holder.item = objects.get(position);
}
Trop simple et efficace.
Au lieu d'implémenter l'interface View.OnClickListener
dans le détenteur de la vue ou de créer et d'interface et d'implémenter l'interface dans votre activité -.__, j'ai utilisé ce code pour une implémentation simple sur OnClickListener
.
public static class SimpleStringRecyclerViewAdapter
extends RecyclerView.Adapter<SimpleStringRecyclerViewAdapter.ViewHolder> {
// Your initializations goes here...
private List<String> mValues;
public static class ViewHolder extends RecyclerView.ViewHolder {
//create a variable mView
public final View mView;
/*All your row widgets goes here
public final ImageView mImageView;
public final TextView mTextView;*/
public ViewHolder(View view) {
super(view);
//Initialize it here
mView = view;
/* your row widgets initializations goes here
mImageView = (ImageView) view.findViewById(R.id.avatar);
mTextView = (TextView) view.findViewById(Android.R.id.text1);*/
}
}
public String getValueAt(int position) {
return mValues.get(position);
}
public SimpleStringRecyclerViewAdapter(Context context, List<String> items) {
mBackground = mTypedValue.resourceId;
mValues = items;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
view.setBackgroundResource(mBackground);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mBoundString = mValues.get(position);
holder.mTextView.setText(mValues.get(position));
//Here it is simply write onItemClick listener here
holder.mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Context context = v.getContext();
Intent intent = new Intent(context, ExampleActivity.class);
context.startActivity(intent);
}
});
}
@Override
public int getItemCount() {
return mValues.size();
}
}
Toutes les réponses publiées jusqu'à présent sont d'excellentes solutions. Toutefois, si vous ne souhaitez pas traiter trop de détails d'implémentation et souhaitez simplement que cela fonctionne de la même manière que ListView, je vous recommanderais d'utiliser TwoWay-View, comme indiqué ici:
https://github.com/lucasr/twoway-view
Notez que cette implémentation prend également en charge une pression longue sur les éléments, ainsi que le support des états pressés (ce qui est une chose importante qui manque aux autres solutions à cette question).
Si vous ne souhaitez pas utiliser la totalité de la bibliothèque, jetez un coup d'œil à la classe ClickItemTouchListener , qui peut être utilisée seule si nécessaire. Le seul problème que j'ai trouvé pour le moment est avec un appui long + défilement, il semble avoir un comportement incorrect.
Si vous voulez capturer l'événement de clic sur les éléments individuels, implémentez simplement OnClickListener
dans la classe ViewHolder
, puis définissez les écouteurs de clic sur des vues individuelles ou sur une itemView
entière.
L'exemple suivant montre le même
public class ContactViewHolder extends RecyclerView.ViewHolder implements OnClickListener
{
TextView txt_title,txt_name,txt_email;
public ContactViewHolder(View itemView)
{
super(itemView);
txt_title = (TextView)itemView.findViewById(R.id.txt_title);
txt_name = (TextView)itemView.findViewById(R.id.txt_name);
txt_email = (TextView)itemView.findViewById(R.id.txt_email);
txt_name.setOnClickListener(this);
txt_email.setOnClickListener(this);
itemView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(v == itemView)
{
Toast.makeText(RecyclerDemoActivity.this, "Visiting Card Clicked is ==>"+txt_name.getText(), Toast.LENGTH_SHORT).show();
}
if(v == txt_name)
{
Toast.makeText(RecyclerDemoActivity.this, "Name ==>"+txt_name.getText(), Toast.LENGTH_SHORT).show();
}
if(v == txt_email)
{
Toast.makeText(RecyclerDemoActivity.this, "Email ==>"+txt_email.getText(), Toast.LENGTH_SHORT).show();
}
}
}
}
Voici ce que j'ai fait En savoir plus et télécharger le Gist ici
Ajout du même ici
CustomItemClickListener.Java
public interface CustomItemClickListener {
public void onItemClick(View v, int position);
}
ItemsListAdapter.Java
public class ItemsListAdapter extends RecyclerView.Adapter<ItemsListAdapter.ViewHolder> {
ArrayList<ItemListSingleItem> data;
Context mContext;
CustomItemClickListener listener;
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View mView = LayoutInflater.from(parent.getContext()).inflate(R.layout.items_list_single_item, parent, false);
final ViewHolder mViewHolder = new ViewHolder(mView);
mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onItemClick(v, mViewHolder.getAdapterPosition());
}
});
return mViewHolder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.itemTitle.setText(Html.fromHtml(data.get(position).getTitle()));
if (!TextUtils.isEmpty(data.get(position).getThumbnailURL())) {
// I Love picasso library :) http://square.github.io/picasso/
Picasso.with(mContext).load(data.get(position).getThumbnailURL()).error(R.drawable.ic_no_image).
placeholder(R.drawable.ic_no_image).
transform(new RoundedCornersTransformation(5, 0)).
into(holder.thumbnailImage);
} else {
holder.thumbnailImage.setImageResource(R.drawable.ic_no_image);
}
}
@Override
public int getItemCount() {
return data.size();
}
public ItemsListAdapter(Context mContext, ArrayList<ItemsListSingleItem> data, CustomItemClickListener listener) {
this.data = data;
this.mContext = mContext;
this.listener = listener;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView itemTitle;
public ImageView thumbnailImage;
ViewHolder(View v) {
super(v);
itemTitle = (TextView) v
.findViewById(R.id.post_title);
thumbnailImage = (ImageView) v.findViewById(R.id.post_thumb_image);
}
}
}
La RecyclerView
n'a pas de OnClickListener
et devra l'implémenter nous-mêmes.
J'aime ajouter une interface OnItemClickListener
dans Adapter
avec une méthode onClick
invoquée lorsque vous cliquez sur la vue de l'élément à partir de la variable ViewHolder
. Ainsi, la responsabilité de gérer le clic sur un élément est en dehors de ViewHolder
et Adapter
. Est-ce que l'activité ou le fragment qui décidera quoi faire
Ajoutez une interface à l'écouteur et à l'objet écouteur.
public class ItemsAdapter extends RecyclerView.Adapter<ItemsAdapter.ViewHolder> {
...
private static OnItemClickListener onItemClickListener;
...
public static interface OnItemClickListener {
public void onItemClick(View view, int position);
}
...
}
Nous capturons le clic de la vue racine de l'élément et, lorsque le rappel est déclenché, l'appel onClick
du programme d'écoute sur l'adaptateur.
public class ItemsAdapter extends RecyclerView.Adapter<ItemsAdapter.ViewHolder> {
...
private static OnItemClickListener onItemClickListener;
...
public static interface OnItemClickListener {
public void onItemClick(View view, int position);
}
...
public static class ViewHolder extends RecyclerView.ViewHolder {
public ImageView imageView;
public ViewHolder(View itemRootView) {
super(itemRootView);
imageView = (ImageView) itemRootView.findViewById(R.id.itemImage);
itemRootView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int position = ViewHolder.super.getAdapterPosition();
onItemClickListener.onItemClick(view,position);
}
});
}
}
}
Depuis l'activité ou le fragment, fragment dans notre cas, nous affectons un écouteur à l'adaptateur et au rappel onClick, nous allons obtenir l'élément sélectionné par position et ouvrir une activité détaillée de l'élément.
public class ItemsFragment extends Fragment {
...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
...
((ItemsAdapter) adapter).setOnItemClickListener(new ItemsAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
//Do something when an item has been clicked
}
});
...
}
...
}
Il manque malheureusement à RecyclerView
quelques fonctionnalités que ListView
avait intégrées . Par exemple, la possibilité d'ajouter une OnItemClickListener
qui se déclenche lorsqu'un utilisateur clique sur un élément. RecyclerView
vous permet de définir une OnClickListener
dans votre adaptateur, mais en transmettant ce clic l’auditeur de votre code d’appel, à l’adaptateur et à la ViewHolder
, est compliqué pour attraper un objet simple, cliquez.
public class ItemClickSupport {
private final RecyclerView mRecyclerView;
private OnItemClickListener mOnItemClickListener;
private OnItemLongClickListener mOnItemLongClickListener;
private View.OnClickListener mOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mOnItemClickListener != null) {
RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
mOnItemClickListener.onItemClicked(mRecyclerView, holder.getAdapterPosition(), v);
}
}
};
private View.OnLongClickListener mOnLongClickListener = new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (mOnItemLongClickListener != null) {
RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
return mOnItemLongClickListener.onItemLongClicked(mRecyclerView, holder.getAdapterPosition(), v);
}
return false;
}
};
private RecyclerView.OnChildAttachStateChangeListener mAttachListener
= new RecyclerView.OnChildAttachStateChangeListener() {
@Override
public void onChildViewAttachedToWindow(View view) {
if (mOnItemClickListener != null) {
view.setOnClickListener(mOnClickListener);
}
if (mOnItemLongClickListener != null) {
view.setOnLongClickListener(mOnLongClickListener);
}
}
@Override
public void onChildViewDetachedFromWindow(View view) {
}
};
private ItemClickSupport(RecyclerView recyclerView) {
mRecyclerView = recyclerView;
mRecyclerView.setTag(R.id.item_click_support, this);
mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener);
}
public static ItemClickSupport addTo(RecyclerView view) {
ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
if (support == null) {
support = new ItemClickSupport(view);
}
return support;
}
public static ItemClickSupport removeFrom(RecyclerView view) {
ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
if (support != null) {
support.detach(view);
}
return support;
}
public ItemClickSupport setOnItemClickListener(OnItemClickListener listener) {
mOnItemClickListener = listener;
return this;
}
public ItemClickSupport setOnItemLongClickListener(OnItemLongClickListener listener) {
mOnItemLongClickListener = listener;
return this;
}
private void detach(RecyclerView view) {
view.removeOnChildAttachStateChangeListener(mAttachListener);
view.setTag(R.id.item_click_support, null);
}
public interface OnItemClickListener {
void onItemClicked(RecyclerView recyclerView, int position, View v);
}
public interface OnItemLongClickListener {
boolean onItemLongClicked(RecyclerView recyclerView, int position, View v);
}
}
Vous devez également définir R.id.item_click_support
à l'aide de ids.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="item_click_support" type="id" />
</resources>
L'écouteur de clic de code obtenu ressemble maintenant à ceci:
ItemClickSupport.addTo(mRecyclerView).setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {
@Override
public void onItemClicked(RecyclerView recyclerView, int position, View v) {
// do it
}
});
Pour une brève explication sur les clics sur recyclerview, jetez un œil à ceci littlerobots_blog
Pour moi, c'est le meilleur moyen:
class YourRecyclerAdapter extends RecyclerView.Adapter<ContactViewHolder> implements View.OnClickListener {
...
@Override
public void onClick(View view) {
int itemPosition = vRecycle.getChildPosition(view);
//And use itemPosition to get the item from your collection. This way you dont restrain the ViewHolder with a OnClick callback
}
...
}
vous pouvez facilement définir setOnClickListener dans votre classe ViewHolder comme suit:
public class ViewHolder extends RecyclerView.ViewHolder {
TextView product_name;
ViewHolder(View itemView) {
super(itemView);
product_name = (TextView) itemView.findViewById(R.id.product_name);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int itemPosition = getLayoutPosition();
Toast.makeText(getApplicationContext(), itemPosition + ":" + String.valueOf(product_name.getText()), Toast.LENGTH_SHORT).show();
}
});
}
}
D'après la plupart des réponses ci-dessus, ils semblent définir leurs listes d'écoute en ligne sur des éléments individuels. Cependant, la solution que je vais proposer est très simple mais n’est pas intuitive pour beaucoup. Beaucoup oublient que les autres composants se trouvent toujours dans un composant parent utilisé pour afficher les éléments dans les vues Liste ou Recycleur. Cette solution consiste simplement à définir un seul auditeur onclick pour cette vue parent et le tour est joué. La solution inclut également un moyen de transmettre la position de l'élément sur lequel l'utilisateur a cliqué à partir de la liste ou de la vue du recycleur. Ici, notre rootview principal est un CardView de la bibliothèque de support Android. Voici un exemple de code
public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ViewHolder> {
public static final String LOG_TAG = ListAdapter.class.getSimpleName();
private Cursor mDataset;
private Context mContext;
private ViewHolder mViewHolder;
// Provide a suitable constructor (depends on the kind of dataset)
public ListAdapter(Context context, Cursor Dataset) {
mDataset = Dataset;
mContext = context;
}
// Create new views (invoked by the layout manager)
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_business_view, parent, false);
mViewHolder = new ViewHolder(v);
return mViewHolder;
}
public void setData(Cursor newdata) {
this.mDataset = newdata;
}
// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
//Bind data to other items here. To save time, i have ommited that.
//here is where we attach a click listerner for an item in the recycler list rather than for each element of a given item.
holder.card.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext, " Just cliked item at position " + itemPosition, Toast.LENGTH_LONG).show();
}
});
}
}
// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
if (null != mDataset) {
return mDataset.getCount();
}
return 0;
}
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class ViewHolder extends RecyclerView.ViewHolder{
// each data item is just a string in this case
public final TextView mBusinesssName; // View for the business name
public final TextView mBusinessCategory; //View for the category name
public final ImageView businessImage; // View for the business category image Image
public final TextView mBusinessDistance; // View for the distance
public final CardView card;
public ViewHolder(View view) {
super(view);
mBusinesssName = (TextView) view.findViewById(R.id.list_item_name_textview);
mBusinessCategory = (TextView) view.findViewById(R.id.list_item_category_textview);
mBusinessDistance = (TextView) view.findViewById(R.id.list_item_dist_textview);
businessImage = (ImageView) view.findViewById(R.id.list_item_icon);
card = (CardView) view.findViewById(R.id.card_view);
}
}
}
Implémentation Kotlin de nhaarman'sréponse :
mRecyclerView.addOnItemTouchListener(object : RecyclerItemClickListener(this, mRecyclerView,object :RecyclerItemClickListener.OnItemClickListener{
override fun onItemClick(view: View, position: Int) {
}
override fun onLongItemClick(view: View?, position: Int) {
}
}){})
RecyclerItemClickListener.Java:
import Android.content.Context
import Android.support.v7.widget.RecyclerView
import Android.view.GestureDetector
import Android.view.MotionEvent
import Android.view.View
open class RecyclerItemClickListener(context: Context, recyclerView: RecyclerView, private val mListener: OnItemClickListener?) : RecyclerView.OnItemTouchListener {
private var mGestureDetector: GestureDetector
interface OnItemClickListener {
fun onItemClick(view: View, position: Int)
fun onLongItemClick(view: View?, position: Int)
}
init {
mGestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapUp(e: MotionEvent): Boolean {
return true
}
override fun onLongPress(e: MotionEvent) {
val child = recyclerView.findChildViewUnder(e.x, e.y)
if (child != null && mListener != null) {
mListener.onLongItemClick(child, recyclerView.getChildAdapterPosition(child))
}
}
})
}
override fun onInterceptTouchEvent(view: RecyclerView, e: MotionEvent): Boolean {
val childView = view.findChildViewUnder(e.x, e.y)
if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
mListener.onItemClick(childView, view.getChildAdapterPosition(childView))
return true
}
return false
}
override fun onTouchEvent(view: RecyclerView, motionEvent: MotionEvent) {}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
}
voici le code complet de mon adaptateur personnalisé. Ce code gonfle les lignes avec les éléments de liste définis dans le fichier XML nommé "list_item". Il effectue également un événement click sur toutes les lignes des éléments de liste avec leurs positions respectives.
public class MyCustomAdapter extends RecyclerView.Adapter`<`AdapterMyCustomAdapter.ViewHolder> {
public static class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener {
public onItemClickListener mListener;
public ViewHolder(View v, onItemClickListener listener) {
super(v);
mListener =listener;
v.setOnClickListener(this);
}
@Override
public void onClick(View v) {
mListener.onRecyclerItemClick(v, getPosition());
}
public static interface onItemClickListener {
public void onRecyclerItemClick(View view , int position);
}
}
@Override
public int getItemCount() {
return 5;
}
@Override
public void onBindViewHolder(ViewHolder holder, int pos) {
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int position) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
/* here list_item is an xml file we want to inflate ...it is same as we do in case of listview for customization.*/
MyCustomAdapter.ViewHolder vh = new ViewHolder(v, new MyCustomAdapter.ViewHolder.onItemClickListener() {
@Override
public void onRecyclerItemClick(View view, int position) {
System.out.println("clicked on list item at position " +position);
}
});
return vh;
}
}
Pour moi, la façon propre de le faire est celle-ci.
Adaptateur constructeur
private class EnvironmentTypeRecyclerViewAdapter extends RecyclerView.Adapter<EnvironmentTypeRecyclerViewAdapter.ViewHolder>
{
private final EnvironmentTypeRecyclerViewAdapterListener mEnvironmentTypeRecyclerViewAdapterListener;
private List<Environment> mEnvironmentsData;
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
{
public ViewHolder(View v)
{
super(v);
v.setOnClickListener(this);
}
@Override
public void onClick(View v)
{
Environment environment = mEnvironmentsData.get(getAdapterPosition());
if (mEnvironmentTypeRecyclerViewAdapterListener != null && environment != null) {
mEnvironmentTypeRecyclerViewAdapterListener.onListItemSelected(environment);
}
}
public EnvironmentTypeRecyclerViewAdapter(List<SmallCellEnvironment> environments, EnvironmentTypeRecyclerViewAdapterListener environmentTypeRecyclerViewAdapterListener)
{
mEnvironmentTypeRecyclerViewAdapterListener = environmentTypeRecyclerViewAdapterListener;
mEnvironmentsData = environments;
}
}
L'interface liée
private interface EnvironmentTypeRecyclerViewAdapterListener
{
void onListItemSelected(Environment environment);
}
Je suis conscient qu'il y a beaucoup de réponses, mais je pensais pouvoir aussi bien en donner la mise en œuvre. (Les détails complets se trouvent sur une autre question à laquelle j'ai répondu ).
Ainsi, pour ajouter un écouteur de clic, votre classe ViewHolder
interne doit implémenter View.OnClickListener
. En effet, vous allez définir une variable OnClickListener
sur le paramètre itemView
du constructeur de la variable ViewHolder
. Laissez-moi vous montrer ce que je veux dire:
public class ExampleClickViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView text1, text2;
ExampleClickViewHolder(View itemView) {
super(itemView);
// we do this because we want to check when an item has been clicked:
itemView.setOnClickListener(this);
// now, like before, we assign our View variables
title = (TextView) itemView.findViewById(R.id.text1);
subtitle = (TextView) itemView.findViewById(R.id.text2);
}
@Override
public void onClick(View v) {
// The user may not set a click listener for list items, in which case our listener
// will be null, so we need to check for this
if (mOnEntryClickListener != null) {
mOnEntryClickListener.onEntryClick(v, getLayoutPosition());
}
}
}
Les seules autres choses que vous devez ajouter sont une interface personnalisée pour votre Adapter
et une méthode de définition:
private OnEntryClickListener mOnEntryClickListener;
public interface OnEntryClickListener {
void onEntryClick(View view, int position);
}
public void setOnEntryClickListener(OnEntryClickListener onEntryClickListener) {
mOnEntryClickListener = onEntryClickListener;
}
Votre nouvelle variable Adapter
prenant en charge les clics est donc complète.
Maintenant, utilisons-le ...
ExampleClickAdapter clickAdapter = new ExampleClickAdapter(yourObjects);
clickAdapter.setOnEntryClickListener(new ExampleClickAdapter.OnEntryClickListener() {
@Override
public void onEntryClick(View view, int position) {
// stuff that will happen when a list item is clicked
}
});
En gros, vous définissez une Adapter
normale, sauf que vous utilisez la méthode de définition que vous avez créée pour contrôler ce que vous ferez lorsque votre utilisateur cliquera sur un élément de la liste.
Vous pouvez également consulter une série d’exemples que j’ai réalisés sur ce Gist sur GitHub:
https://Gist.github.com/FarbodSalamat-Zadeh/7646564f48ee708c1582c013e1de4f07
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView title, year, genre;
public MyViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.title);
genre = (TextView) view.findViewById(R.id.genre);
year = (TextView) view.findViewById(R.id.year);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, ""+getAdapterPosition(), Toast.LENGTH_SHORT).show();
}
});
}
}
C’est ce que je fais pour réutiliser OnClickListener
public class TestAdapter extends RecyclerView.Adapter<TestAdapter.MyviewHolder>
implements View.OnClickListener
dans ViewHoder Prendre le parent de itemlayout
public class MyviewHolder extends RecyclerView.ViewHolder {
LinearLayout linearLayout_item;
public MyviewHolder(View itemView) {
super(itemView);
linearLayout_item=itemView.findViewById(R.id.linearLayout_item);
}
}
dans onBindViewHolder définit la balise comme position
@Override
public void onBindViewHolder(MyviewHolder holder, int position) {
holder.linearLayout_item.setTag(position);
holder.linearLayout_item.setOnClickListener(this);
}
et à Onclick
@Override
public void onClick(View v) {
int position = (int) v.getTag();
switch (v.getId()) {
case R.id.linearLayout_item:
// do some thing with position
break;
}
}
En kotlin avec implémentation constructeur
Initialisez votre constructeur Recyclerview comme ci-dessous
class ListAdapter(
c: Context,
private var list: List<Project>,
private val itemClick: (Project) -> Unit
) : RecyclerView.Adapter<ListAdapter.ViewHolder>()
retourner avec itemClick dans votre onCreateViewHolder
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):ProjectViewHolder {
val view = inflater.inflate(R.layout.list_item, parent, false)
return ViewHolder(view, itemClick)
}
Votre onBindViewHolder
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bindProject(list[position])
}
Ensuite, avec la classe viewHolder, créez la fonction bindProject.
class ViewHolder(
view: View,
private val itemClick: (Project) -> Unit
) : RecyclerView.ViewHolder(view) {
private val clientTextCount = 7
val titleTextView: TextView = view.projectTitleTextView
fun bindProject(project: Project) {
with(project) {
titleTextView.text = name
itemView.setOnClickListener { itemClick(this) }
}
}
}
Enfin, dans votre activité, initialisez l’adaptateur avec lazy
private val adapter: ListAdapter by lazy {
ListAdapter(this, projectList, {
// Here you can implement your onClick function.
})
}
Pour ajouter une nouvelle liste à recyclerview, initialisez la méthode ci-dessous dans votre adaptateur
fun setProjects(projects: List<Project>) {
projectList = projects
notifyDataSetChanged()
}
et appelez la méthode setProjects n’importe où dans votre activité.
adapter.setProjects(projects)
C'est tout.
J'ai examiné toutes les réponses et je n'étais pas tout à fait satisfait. J'ai trouvé une solution beaucoup plus facile et plus rapide. Voulait partager pour les futurs lecteurs.
View
dans votre article de recycleur unique. View
(Assurez-vous que vous avez le rôle approprié pour approuver ViewGroup
)onClickListener
sur ce parent. Exemple de code (il est écrit dans votre méthode onBindViewHolder
de votre adapter
):
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
ConstraintLayout parent = (ConstraintLayout) holder.title.getParent();
parent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, "Clicked recycler view item at position " + position, Toast.LENGTH_SHORT).show();
}
});
}
Voici mon extrait de code
v.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v)
{
int newposition = MainActivity.mRecyclerView.getChildAdapterPosition(v);
Intent cardViewIntent = new Intent(c, in.itechvalley.cardviewexample.MainActivityCards.class);
cardViewIntent.putExtra("Position", newposition);
c.startActivity(cardViewIntent);
}
});
v
est Vue de onCreateViewHolder
c
est Contexte
Voyons comment nous pouvons également implémenter cela avec Jetpack/AndroidX
Vous devez créer un observable dans la classe viewmodel comme ceci
private MutableLiveData<Integer> adapterItem = new MutableLiveData<>();
public MutableLiveData<Integer> getAdapterItem() {
return adapterItem;
}
public void setAdapterItem(int adapterItem) {
this.getAdapterItem().setValue(adapterItem);
}
Ensuite, dans la classe adaptateur, assurez-vous de passer la référence de viewmodel en tant que paramètre dans le constructeur, puis implémentez le clicklistener sur le détenteur.
public MyViewHolder(@NonNull View itemView) {
super(itemView);
if(itemView != null){
itemView.setOnClickListener(v -> {
int adapterPosition = getAdapterPosition();
viewModel.setAdapterItem(adapterPosition);
});
};
}
Ensuite, à partir de la classe activité, observez simplement les modifications.
viewModel.getAdapterItem().observe(this, position -> {
Log.w(TAG, "clicked: " + ridesArray.get(position));
});
Marque la classe comme abstraite et implémente une méthode OnClick
public abstract class MainGridAdapter extends
RecyclerView.Adapter<MainGridAdapter.ViewHolder> {
private List<MainListItem> mDataset;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView txtHeader;
public TextView txtFooter;
public ViewHolder(View v) {
super(v);
txtHeader = (TextView) v.findViewById(R.id.firstLine);
txtFooter = (TextView) v.findViewById(R.id.secondLine);
}
}
public void add(int position, MainListItem item) {
mDataset.add(position, item);
notifyItemInserted(position);
}
public void remove(MainListItem item) {
int position = mDataset.indexOf(item);
mDataset.remove(position);
notifyItemRemoved(position);
}
// Provide a suitable constructor (depends on the kind of dataset)
public MainGridAdapter(List<MainListItem> myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
@Override
public MainGridAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.list_item_grid_line, parent, false);
// set the view's size, margins, paddings and layout parameters
ViewHolder vh = new ViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
OnClickListener clickListener = new OnClickListener() {
@Override
public void onClick(View v) {
onItemClicked(position);
}
};
holder.itemView.setOnClickListener(clickListener);
holder.txtHeader.setOnClickListener(clickListener);
holder.txtFooter.setOnClickListener(clickListener);
final MainListItem item = mDataset.get(position);
holder.txtHeader.setText(item.getTitle());
if (TextUtils.isEmpty(item.getDescription())) {
holder.txtFooter.setVisibility(View.GONE);
} else {
holder.txtFooter.setVisibility(View.VISIBLE);
holder.txtFooter.setText(item.getDescription());
}
}
// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
return mDataset.size();
}
public abstract void onItemClicked(int position);
}
Implémenter le gestionnaire de clics dans un événement de liaison pour n'avoir qu'une implémentation d'événement
Mise en œuvre de ceci:
mAdapter = new MainGridAdapter(listItems) {
@Override
public void onItemClicked(int position) {
showToast("Item Clicked: " + position, ToastPlus.STYLE_INFO);
}
};
La même chose peut être faite pour un clic long
Nous pouvons faire cela en utilisant des références Java faibles . Sémantiquement, le détenteur de la vue est celui qui doit répondre à l'événement click ou le déléguer au bon répondeur.
Nos buts:
Pas:
Créez une interface pour gérer les réponses au clic.
Implémentez cette interface dans l'activité qui gérera le clic.
Ajoutez une variable membre dans l'adaptateur RecyclerView pour contenir la référence faible et un constructeur qui la définit.
Faites la même chose dans le RecyclerView ViewHolder et ajoutez une variable membre pour garder une trace de la position.
Définissez vos écouteurs sur un clic sur la vue de votre choix dans ViewHolder, puis rappelez au répondeur de les gérer.
Modifiez votre méthode onBindViewHolder pour définir la position lors de la liaison.
Transmettez le répondeur au ViewHolder.
Dans le répondeur, vous pouvez maintenant utiliser getId () sur la vue pour déterminer la vue sur laquelle vous avez cliqué.
Et voici un résumé pour vous permettre de voir comment tout cela s’agence: Traitement des clics RecyclerView
Voici une stratégie qui donne un résultat similaire à l'implémentation ListView
en ce sens que vous pouvez définir l'auditeur au niveau Activity
ou Fragment
au lieu du niveau Adapter
ou ViewHolder
Il définit également des classes abstraites qui prennent en charge une grande partie du travail standard des adaptateurs et des détenteurs.
Commencez par définir un résumé Holder
qui étend RecyclerView.ViewHolder
et définit un type de données générique, T
, utilisé pour lier les données aux vues. La méthode bindViews
sera implémentée par une sous-classe pour mapper les données aux vues.
public abstract class Holder<T> extends RecyclerView.ViewHolder {
T data;
public Holder(View itemView) {
super(itemView);
}
public void bindData(T data){
this.data = data;
bindViews(data);
}
abstract protected void bindViews(T data);
}
Créez également un résumé Adapter
qui étend RecyclerView.Adapter<Holder<T>>
. Cela définit 2 des 3 méthodes d'interface et une sous-classe devra implémenter la dernière méthode, onViewHolderCreated
.
public abstract class Adapter<T> extends RecyclerView.Adapter<Holder<T>> {
List<T> list = new ArrayList<>();
@Override
public void onBindViewHolder(Holder<T> holder, int position) {
holder.bindData(list.get(position));
}
@Override
public int getItemCount() {
return list.size();
}
public T getItem(int adapterPosition){
return list.get(adapterPosition);
}
}
Créez maintenant une nouvelle classe concrète qui étend Holder
. Cette méthode doit seulement définir les vues et gérer la liaison. Ici, j'utilise la bibliothèque ButterKnife , mais n'hésitez pas à utiliser les méthodes itemView.findViewById(...)
à la place.
public class PersonHolder extends Holder<Person>{
@Bind(R.id.firstname) TextView firstname;
@Bind(R.id.lastname) TextView lastname;
public PersonHolder(View view){
super(view);
ButterKnife.bind(this, view);
}
@Override
protected void bindViews(Person person) {
firstname.setText(person.firstname);
lastname.setText(person.lastname);
}
}
Enfin, dans votre classe Activity
ou Fragment
qui contient le RecyclerView
, vous auriez ce code:
// Create adapter, this happens in parent Activity or Fragment of RecyclerView
adapter = new Adapter<Person>(){
@Override
public PersonHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.layout_person_view, parent, false);
PersonHolder holder = new PersonHolder(v);
v.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
int itemPos = holder.getAdapterPosition();
Person person = getItem(itemPos);
// do something with person
EventBus.getDefault().postSticky(new PersonClickedEvent(itemPos, person));
}
});
return holder;
}
};
Très simple, ajoutez cette classe:
public class OnItemClickListener implements View.OnClickListener {
private int position;
private OnItemClickCallback onItemClickCallback;
public OnItemClickListener(int position, OnItemClickCallback onItemClickCallback) {
this.position = position;
this.onItemClickCallback = onItemClickCallback;
}
@Override
public void onClick(View view) {
onItemClickCallback.onItemClicked(view, position);
}
public interface OnItemClickCallback {
void onItemClicked(View view, int position);
}
}
Obtenez une instance de l'interface 'OnItemClickCallback' et mettez-la dans votre activité ou dans votre fragment:
private OnItemClickListener.OnItemClickCallback onItemClickCallback = new OnItemClickListener.OnItemClickCallback() {
@Override
public void onItemClicked(View view, int position) {
}
};
Ensuite, transmettez ce rappel à votre recyclerView:
recyclerView.setAdapter(new SimpleStringRecyclerViewAdapter(Arrays.asList("1", "2", "3"), onItemClickCallback));
Enfin, ce serait votre adaptateur:
public class SimpleStringRecyclerViewAdapter extends RecyclerView.Adapter<SimpleStringRecyclerViewAdapter.ViewHolder> {
private List<String> mValues;
private OnItemClickListener.OnItemClickCallback onItemClickCallback;
public SimpleStringRecyclerViewAdapter(List<String> items, OnItemClickListener.OnItemClickCallback onItemClickCallback) {
mValues = items;
this.onItemClickCallback = onItemClickCallback;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public final TextView mTextView;
public ViewHolder(View view) {
super(view);
mTextView = (TextView) view.findViewById(R.id.txt_title);
}
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.mTextView.setText(mValues.get(position));
holder.mTextView.setOnClickListener(new OnItemClickListener(position, onItemClickCallback));
}
@Override
public int getItemCount() {
return mValues.size();
}
}
Étape 1) Écrire l'interface de clic
Créez une interface nommée RecyclerViewClickListener.Java et ajoutez le code ci-dessous. Nous déclarons ici deux méthodes onClick et onLongClick pour identifier les clics d’éléments et les clics longs.
package com.androidtutorialshub.recyclerviewtutorial.Helper;
import Android.view.View;
public interface RecyclerViewClickListener {
void onClick(View view, int position);
void onLongClick(View view, int position);
}
Étape 2) Écrire l'élément Item Touch Class
Créez une classe nommée RecyclerViewTouchListener.Java et ajoutez le code ci-dessous. Nous écrivons ici la logique permettant de détecter les clics et d’appuyer longuement sur un élément de la vue recycleur.
package com.androidtutorialshub.recyclerviewtutorial.Helper;
import Android.content.Context;
import Android.support.v7.widget.RecyclerView;
import Android.view.GestureDetector;
import Android.view.MotionEvent;
import Android.view.View;
public class RecyclerViewTouchListener implements RecyclerView.OnItemTouchListener{
private GestureDetector gestureDetector;
private RecyclerViewClickListener clickListener;
public RecyclerViewTouchListener(Context context, final RecyclerView recyclerView, final RecyclerViewClickListener clickListener) {
this.clickListener = clickListener;
gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
@Override
public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null) {
clickListener.onLongClick(child, recyclerView.getChildPosition(child));
}
}
});
}
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
clickListener.onClick(child, rv.getChildPosition(child));
}
return false;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
Étape 3) Définir un écouteur de clic
Ouvrez MainActivity.Java et mettez à jour les modifications ci-dessous. Ici, la méthode onClick () détectera un clic sur un élément et onLongClick détectera un clic long sur un élément.
recyclerView.addOnItemTouchListener(new RecyclerViewTouchListener(getApplicationContext(), recyclerView, new RecyclerViewClickListener() {
@Override
public void onClick(View view, int position) {
Toast.makeText(getApplicationContext(), bookList.get(position).getTitle() + " is clicked!", Toast.LENGTH_SHORT).show();
}
@Override
public void onLongClick(View view, int position) {
Toast.makeText(getApplicationContext(), bookList.get(position).getTitle() + " is long pressed!", Toast.LENGTH_SHORT).show();
}
}));
Pour plus d'informations ou télécharger le code source: - http://www.androidtutorialshub.com/Android-recyclerview-click-listener-tutorial/
Essayez ceci, assez simple. Ça marche pour moi. BTW, j'ai trouvé que setOnClickListener
ne prend pas effet pour la vue recycleur.
recycler.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
// anything todo
}
return true;
}
});
Même réponse à Kotlin
inner class MyViewHolder(v: View, myOnClickListener: MyOnClickListener) : RecyclerView.ViewHolder(v) {
init {
v.setOnClickListener { v -> myOnClickListener.onClick(v, adapterPosition) }
}
}
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): MyViewHolder {
val view = LayoutInflater.from(viewGroup.context).inflate(R.layout.myview, viewGroup, false)
return MyViewHolder(view, mOnClickListener)
}
inner class MyOnClickListener {
fun onClick(view: View, position: Int) {
val item = mList[position]
Toast.makeText(view.context, item, Toast.LENGTH_LONG).show()
}
}
Pour le manche en kotlin, cliquez sur recyclerview anser basé sur Jacobs anser
1) CREATE CLASS RecyclerItemClickListener
class RecyclerItemClickListener(context: Context, recyclerView: RecyclerView, listner: OnItemClickListener) : RecyclerView.OnItemTouchListener {
var mGestureDetector: GestureDetector
var mListner: OnItemClickListener
interface OnItemClickListener {
fun onItemClick(view: View, position: Int)
fun onLongItemClick(view: View, position: Int)
}
init {
this.mListner = listner
mGestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapUp(e: MotionEvent?): Boolean {
return true
}
override fun onLongPress(e: MotionEvent?) {
val child: View? = recyclerView.findChildViewUnder(e!!.getX(), e.getY())
if (child != null && mListner != null) {
mListner.onLongItemClick(child, recyclerView.getChildAdapterPosition(child))
}
}
})
}
override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {
}
override fun onInterceptTouchEvent(view: RecyclerView, e: MotionEvent): Boolean {
val childView: View? = view.findChildViewUnder(e!!.getX(), e.getY())
if (childView != null && mListner != null && mGestureDetector.onTouchEvent(e)) {
mListner.onItemClick(childView, view.getChildAdapterPosition(childView))
return true
}
return false
}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {
}
}
2) get Cliquez sur un recyclage (activité/fragment)
recyclerView.addOnItemTouchListener(
RecyclerItemClickListener(
this, recyclerView, object : RecyclerItemClickListener.OnItemClickListener {
override fun onItemClick(view: View, position: Int) {
}
override fun onLongItemClick(view: View, position: Int) {
}
})
)
Voici une façon simple et claire d’ajouter ReacyclerView
ViewHolder
public static class MyViewholder extends RecyclerView.ViewHolder {
public MyViewholder(View itemView) {
super(itemView);
itemView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.d("Tag", "onClick:" + getAdapterPosition());
}
});
}
}
getAdapterPosition()
est la position actuelle de l'élément cliqué
En règle générale, votre CardView
contient plusieurs éléments, de sorte que vous avez besoin d'un mode d'affichage pour les envelopper et les organiser.
Vous pouvez ajouter une OnClickListener
à cette vue.
1. Ajoutez un identifiant à votre mise en page. Dans ce cas, une LinearLayout
<Android.support.v7.widget.CardView
.....>
<LinearLayout
Android:orientation="vertical"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:id="@+id/card_view_linearLayout">
<TextView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="name"
Android:id="@+id/card_view_name" />
...
</LinearLayout>
</Android.support.v7.widget.CardView>
$
2. Obtenez la vue de présentation dans votre classe ViewHolder
intérieure.
public static class ViewHolder extends RecyclerView.ViewHolder{
private TextView nameView;
...
private LinearLayout linearLayout;
public ViewHolder(View itemView) {
super(itemView);
nameView = (TextView)itemView.findViewById(R.id.card_view_name);
...
linearLayout = (LinearLayout)itemView.findViewById(R.id.card_view_linearLayout);
}
}
$
3. Ajoutez l'écouteur à votre mise en page dans onBindViewHolder
et utilisez un rappel pour envoyer des données à Activity
ou Fragment
(non testé).
@Override
public void onBindViewHolder(TrackAdapter.ViewHolder holder, final int position) {
String str = mStringList.get(position);
holder.nameView.setText(str);
...
holder.linearLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
callback.itemCallback(mStringList.get(position));
}
});
}
comment utiliser les rappels est une autre histoire