Hat jemand, der RecyclerView
verwendet, einen Weg gefunden, um einen onClickListener
für Elemente im RecyclerView
festzulegen? Ich dachte daran, für jedes Element einen Listener für jedes Layout festzulegen, aber das scheint etwas zu umständlich zu sein. Ich bin sicher, dass es eine Möglichkeit gibt, dass der RecyclerView
auf das onClick
-Ereignis hört, aber ich kann es nicht ganz herausfinden.
Antworten
Zu viele Anzeigen?Für mich ist das der beste Weg:
class YourRecyclerAdapter extends RecyclerView.Adapter implements View.OnClickListener {
...
@Override
public void onClick(View view) {
int itemPosition = vRecycle.getChildPosition(view);
//Und verwenden itemPosition, um den Artikel aus Ihrer Sammlung zu erhalten. Auf diese Weise beschränken Sie den ViewHolder nicht mit einem OnClick-Callback
}
...
}
Hier ist, was ich gemacht habe Hier weiterlesen und den Gist herunterladen
Hier dasselbe hinzufügen
CustomItemClickListener.java
public interface CustomItemClickListener {
public void onItemClick(View v, int position);
}
ItemsListAdapter.java
public class ItemsListAdapter extends RecyclerView.Adapter {
ArrayList 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())) {
// Ich liebe die Picasso-Bibliothek :) 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 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);
}
}
}
Ein Klick-Listener wird innerhalb Ihres ViewHolder
auf folgende Weise eingerichtet:
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();
}
});
}
}
Aus den meisten der obigen Antworten scheinen sie ihre onclicklistener auf einzelne Elemente zu setzen. Die Lösung, die ich gleich anbieten werde, ist jedoch sehr einfach, aber für viele nicht intuitiv. Viele vergessen, dass die anderen Komponenten immer in einer übergeordneten Komponente sind, die verwendet wird, um Elemente in den Listen- oder Recycler-Ansichten anzuzeigen. Diese Lösung besteht darin, einen einzigen onclick-Listener auf diese übergeordnete Ansicht zu setzen und dann wird die Aktion ausgeführt. Die Lösung beinhaltet auch eine Möglichkeit, die Position des angeklickten Elements aus der Liste oder RecyclerView zu übergeben. Hier ist unser Haupt-Rootview eine CardView aus der Android-Support-Bibliothek. Hier ist ein Beispielcode
public class ListAdapter extends RecyclerView.Adapter {
public static final String LOG_TAG = ListAdapter.class.getSimpleName();
private Cursor mDataset;
private Context mContext;
private ViewHolder mViewHolder;
// Bieten Sie einen geeigneten Konstruktor an (abhängig von der Art des Datensatzes)
public ListAdapter(Context context, Cursor Dataset) {
mDataset = Dataset;
mContext = context;
}
// Erstellen neuer Ansichten (aufgerufen vom Layout-Manager)
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// neue Ansicht erstellen
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;
}
// Ersetzen Sie den Inhalt einer Ansicht (aufgerufen vom Layout-Manager)
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
// Daten an andere Elemente binden. Um Zeit zu sparen, habe ich das hier ausgelassen.
//Hier setzen wir einen Klicklistener für ein Element in der Recycler-Liste anstelle jedes Elements eines bestimmten Elements.
holder.card.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext, " Nur auf Element an Position geklickt " + itemPosition, Toast.LENGTH_LONG).show();
}
});
}
}
// Gib die Größe deines Datensatzes zurück (aufgerufen vom Layout-Manager)
@Override
public int getItemCount() {
if (null != mDataset) {
return mDataset.getCount();
}
return 0;
}
// Bieten Sie einen Verweis auf die Ansichten für jedes Datenelement an
// Komplexe Datenelemente benötigen möglicherweise mehr als eine Ansicht pro Element, und
// Sie haben Zugriff auf alle Ansichten für ein Datenelement in einem Ansichtshalter
public static class ViewHolder extends RecyclerView.ViewHolder{
// jedes Datenelement ist in diesem Fall nur ein String
public final TextView mBusinesssName; // Ansicht für den Firmennamen
public final TextView mBusinessCategory; // Ansicht für den Kategorienamen
public final ImageView businessImage; // Ansicht für das Bild der Firmenkategorie
public final TextView mBusinessDistance; // Ansicht für die Entfernung
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);
}
}
}
Kotlin-Implementierung von nhaarman's Antwort:
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) {}
}