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?Wir können dies mit Hilfe von Java-Schwachreferenzen erreichen. Semantisch gesehen ist der Ansichtshalter derjenige, der auf das Klickereignis reagieren oder es an den richtigen Empfänger delegieren sollte.
Unsere Ziele:
- Der Viewholder sollte nichts über die Klasse wissen, die auf die Ereignisse reagiert, außer dass sie eine bestimmte Schnittstelle implementiert.
- Der Klick-Handler sollte die Position im RecyclerView des angeklickten Elements erhalten.
- Wir sollten unterscheiden können, welches Element im Ansichtshalter angeklickt wurde.
- Locker gekoppelte zwischen allen Komponenten erhalten und keine Schleifenbeziehungen verursachen.
Schritte:
-
Erstellen Sie eine Schnittstelle zur Behandlung von Klickereignissen.
-
Implementieren Sie diese Schnittstelle in der Aktivität, die den Klick behandeln wird.
-
Fügen Sie dem RecyclerView-Adapter eine Member-Variable hinzu, um die Schwachreferenz zu halten, und einen Konstruktor, der sie setzt.
-
Das Gleiche im RecyclerView ViewHolder durchführen und eine Member-Variable hinzufügen, um die Position nachzuverfolgen.
-
Setzen Sie Ihre Klick-Listener auf jedes beliebige Element im ViewHolder und rufen Sie dann zum Behandeln den Empfänger auf.
-
Ändern Sie Ihre onBindViewHolder-Methode, um die Position beim Binden zu setzen.
-
Reichen Sie den Empfänger an den ViewHolder weiter.
-
Im Empfänger können Sie jetzt getId() auf dem Element verwenden, um herauszufinden, welches Element angeklickt wurde.
Und hier ist ein Gist, damit Sie sehen können, wie alles zusammenpasst: Klickenbehandlung mit RecyclerView
Für mich ist der saubere Weg, das zu tun, dieser.
Adapter-Konstruktor
private class EnvironmentTypeRecyclerViewAdapter extends RecyclerView.Adapter
{
private final EnvironmentTypeRecyclerViewAdapterListener mEnvironmentTypeRecyclerViewAdapterListener;
private List 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 environments, EnvironmentTypeRecyclerViewAdapterListener environmentTypeRecyclerViewAdapterListener)
{
mEnvironmentTypeRecyclerViewAdapterListener = environmentTypeRecyclerViewAdapterListener;
mEnvironmentsData = environments;
}
}
Das verbundene Interface
private interface EnvironmentTypeRecyclerViewAdapterListener
{
void onListItemSelected(Environment environment);
}
Fügen Sie in Ihrer Adapterklasse eine Schnittstelle hinzu.
public interface SelectedUser{
void selectedUser(UserModel userModel);
}
Implementieren Sie Ihre Schnittstelle in der MainActivity und überschreiben Sie die Methode selectedUser.
@Override
public void selectedUser(UserModel userModel) {
startActivity(new Intent(MainActivity.this, SelectedUserActivity.class).putExtra("data",userModel));
}
Vollständiges Tutorial finden Sie hier plus Quellcode. Recyclerview mit Clicklistener und Suchansicht
In kotlin with constructor implementation
Initialisieren Sie Ihren RecyclerView
-Konstruktor wie unten gezeigt:
class ListAdapter(
c: Context,
private var list: List,
private val itemClick: (Project) -> Unit
) : RecyclerView.Adapter()
Geben Sie itemClick
in Ihrem onCreateViewHolder
zurück:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):ProjectViewHolder {
val view = inflater.inflate(R.layout.list_item, parent, false)
return ViewHolder(view, itemClick)
}
Ihr onBindViewHolder
:
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bindProject(list[position])
}
Erstellen Sie dann mit der ViewHolder
-Klasse die Funktion 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) }
}
}
}
Initialisieren Sie schließlich in Ihrer Aktivität den Adapter mit lazy
private val adapter: ListAdapter by lazy {
ListAdapter(this, projectList, {
// Hier können Sie Ihre onClick-Funktion implementieren.
})
}
Fügen Sie zur Hinzufügung einer neuen Liste zum RecyclerView
die untenstehende Methode in Ihrem Adapter hinzu:
fun setProjects(projects: List) {
projectList = projects
notifyDataSetChanged()
}
Und rufen Sie die Methode setProjects
überall in Ihrer Aktivität auf:
adapter.setProjects(projects)
Das war's.
Dies ist, was ich tue, um View.OnClickListener
wiederzuverwenden:
public class TestAdapter extends RecyclerView.Adapter
implements View.OnClickListener
In ViewHoder
nehmen Sie das Elternansichtselement des Element-Layouts:
public class MyviewHolder extends RecyclerView.ViewHolder {
LinearLayout linearLayout;
public MyviewHolder(View itemView) {
super(itemView);
linearLayout = itemView.findViewById(R.id.linear_layout_item);
}
}
In onBindViewHolder
setzen Sie das Tag als Position:
@Override
public void onBindViewHolder(MyviewHolder holder, int position) {
holder.linearLayout.setTag(position);
holder.linearLayout.setOnClickListener(this);
}
Und innerhalb Ihrer onClick
-Realisierung:
@Override
public void onClick(View v) {
int position = (int) v.getTag();
switch (v.getId()) {
case R.id.linear_layout_item:
// etwas mit der Position machen
break;
}
}