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?Klassen als abstrakt markieren und eine OnClick-Methode implementieren
public abstract class MainGridAdapter extends
RecyclerView.Adapter {
private List mDataset;
// Referenz auf die Ansichten für jedes Datenelement bereitstellen
// Komplexe Datenelemente benötigen möglicherweise mehr als eine Ansicht pro Element und
// Sie ermöglichen den Zugriff auf alle Ansichten für ein Datenelement in einem Ansichtshalter
public class ViewHolder extends RecyclerView.ViewHolder {
// jedes Datenelement ist in diesem Fall nur ein String
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);
}
// Geeigneten Konstruktor bereitstellen (abhängig von der Art des Datensatzes)
public MainGridAdapter(List myDataset) {
mDataset = myDataset;
}
// Neue Ansichten erstellen (aufgerufen vom Layout-Manager)
@Override
public MainGridAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// neue Ansicht erstellen
View v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.list_item_grid_line, parent, false);
// Größe, Ränder, Abstände und Layoutparameter der Ansicht festlegen
ViewHolder vh = new ViewHolder(v);
return vh;
}
// Inhalt einer Ansicht ersetzen (aufgerufen vom Layout-Manager)
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
// - Element aus Ihrem Datensatz an dieser Position abrufen
// - Inhalt der Ansicht durch dieses Element ersetzen
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());
}
}
// Größe des Datensatzes zurückgeben (aufgerufen vom Layout-Manager)
@Override
public int getItemCount() {
return mDataset.size();
}
public abstract void onItemClicked(int position);
}
Klicken-Handler in Bindungsereignis implementieren, um nur eine Ereignisimplementierung zu haben
Implementierung davon:
mAdapter = new MainGridAdapter(listItems) {
@Override
public void onItemClicked(int position) {
showToast("Element angeklickt: " + position, ToastPlus.STYLE_INFO);
}
};
Dasselbe kann für einen Langklick erfolgen
Recyclerview-Adapter mit Kotlin
Sie können den Elementklicklistener auf zwei Arten im Adapter erreichen.
Die erste Möglichkeit besteht darin, ein Interface zu verwenden
In Ihrer Aktivitätsklasse:
class YourActivity : AppCompatActivity(), TestAdapter.ClickListener {
...
override fun itemClicked() {
}
...
}
In Ihrer Adapterklasse:
class MyAdapter : RecyclerView.Adapter {
...
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.textView1.setOnClickListener {
clickListener.itemClicked(position)
}
}
...
interface ClickListener {
fun itemClicked(position : Int)
}
...
}
Die zweite Möglichkeit besteht darin, den Callback aufzurufen
In Ihrer Adapterklasse:
class MyAdapter(val callBack: (pos:Int) -> Unit) : RecyclerView.Adapter {
...
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.textView1.setOnClickListener {
callBack(position)
}
}
}
In Ihrer Aktivitätsklasse:
class YourActivity : AppCompatActivity() {
...
val testAdapter = TestAdapter(
callBack = { index ->
})
binding.recyclerView.layoutManager = LinearLayoutManager(this)
binding.recyclerView.adapter = testAdapter
...
}
Für Kotlin Klick auf RecyclerView
Antwort basierend auf Jacobs Antwort
Erstellen Sie die Klasse 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 = 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) = Unit
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) = Unit
}
Klicke auf ein beliebiges RecyclerView
(innerhalb der Activity/Fragment):
recyclerView.addOnItemTouchListener(
RecyclerItemClickListener(this, recyclerView, object : RecyclerItemClickListener.OnItemClickListener {
override fun onItemClick(view: View, position: Int) {
// TODO Klick erfassen
}
override fun onLongItemClick(view: View, position: Int) {
// TODO Klick erfassen
}
})
)
Gleiche Antwort in 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()
}
}
Schritt 1 ) Schreiben der Klick-Schnittstelle
Erstellen Sie eine Schnittstelle mit dem Namen RecyclerViewClickListener.java und fügen Sie den unten stehenden Code hinzu. Hier deklarieren wir zwei Methoden onClick und onLongClick, um jeweils einen Klick und einen langen Klick zu identifizieren.
package com.androidtutorialshub.recyclerviewtutorial.Helper;
import android.view.View;
public interface RecyclerViewClickListener {
void onClick(View view, int position);
void onLongClick(View view, int position);
}
Schritt 2 ) Schreiben der Item-Touch-Klasse
Erstellen Sie eine Klasse mit dem Namen RecyclerViewTouchListener.java und fügen Sie den unten stehenden Code hinzu. Hier schreiben wir die Logik zur Erkennung von Klick und langem Druck auf das RecyclerView-Element.
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) {
}
}
Schritt 3 ) Definieren des Klick-Listeners
Öffnen Sie MainActivity.java und aktualisieren Sie die unten stehenden Änderungen. Hier wird die Methode onClick() einen Klick auf das Element erkennen und onLongClick wird einen langen Klick auf das Element erkennen.
recyclerView.addOnItemTouchListener(new RecyclerViewTouchListener(getApplicationContext(), recyclerView, new RecyclerViewClickListener() {
@Override
public void onClick(View view, int position) {
Toast.makeText(getApplicationContext(), bookList.get(position).getTitle() + " wurde geklickt!", Toast.LENGTH_SHORT).show();
}
@Override
public void onLongClick(View view, int position) {
Toast.makeText(getApplicationContext(), bookList.get(position).getTitle() + " wurde lange gedrückt!", Toast.LENGTH_SHORT).show();
}
}));
Für weitere Informationen oder zum Herunterladen des Quellcodes :- http://www.androidtutorialshub.com/android-recyclerview-click-listener-tutorial/