677 Stimmen

RecyclerView onClick

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.

4voto

ccpizza Punkte 24937

Erfinden Sie das Rad nicht neu! Der Code für diesen speziellen Anwendungsfall ist im Master/Detail Flow Starterprojekt enthalten, das mit Android Studio geliefert wird.

Wählen Sie in Android Studio aus:

  1. Datei > Neu > Neues Projekt....
  2. Wählen Sie im Tab Telefon und Tablet <strong>Master/Detail Flow</strong> wie unten dargestellt.

Bildbeschreibung hier eingeben

  1. Erstellen Sie das Projekt entweder in Kotlin oder Java.
  2. Profitieren Sie.

Ich werde hier nicht den Code aus Googles Out-of-the-Box-Demo-Projekt einbeziehen, aber ich werde die Hauptentwurfsansätze in der von Google bereitgestellten Beispiel anreißen:

  • Der Element-OnClickListener wird NUR EINMAL erstellt und einem Feld in Ihrer RecyclerView.Adapter-Implementierung zugewiesen.
  • In der onBindViewHolder() sollten Sie derselben, vorher erstellten onClickListener-Objekt auf Ihrer ViewHolder-Instanz mit holder.itemView.setOnClickListener(mOnClickListener) setzen (Vermeiden Sie das Erstellen einer neuen Instanz bei jedem Methodenaufruf!); wenn Sie Klicks auf bestimmte Elemente innerhalb des ViewHolders erfassen müssen, erweitern Sie ViewHolder und machen Sie die benötigten Elemente als Felder zugänglich, damit Sie die erforderlichen Listener in onBindViewHolder() anhängen können— und nochmals, erstellen Sie die Listener nicht bei jedem Methodenaufruf neu—initialisieren Sie sie als Instanzfelder und fügen Sie sie nach Bedarf an.
  • Sie können .setTag() verwenden, um Zustand an Ihren ViewHolder zu übergeben, z.B. holder.itemView.setTag(mValues.get(position)); wie in der Demo verwendet.

4voto

Vipul Prajapati Punkte 1103

Hier ist eine einfache und klare Möglichkeit, sie innerhalb Ihres ReacyclerView ViewHolder hinzuzufügen

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() gibt die aktuelle Position des angeklickten Elements zurück

4voto

anand krish Punkte 3595

Leider fehlen dem RecyclerView einige Funktionen, die im ListView eingebaut waren. Zum Beispiel die Möglichkeit, einen OnItemClickListener hinzuzufügen, der ausgelöst wird, wenn ein Element angeklickt wird. Das RecyclerView ermöglicht es Ihnen, einen OnClickListener in Ihrem Adapter festzulegen, aber das Weiterleiten dieses Klicks Listeners von Ihrem Aufrufcode über den Adapter bis zum ViewHolder ist kompliziert, um einen einfachen Elementklick zu erfassen.

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);
}
}

Sie müssen auch R.id.item_click_support in der Datei ids.xml definieren:

Der resultierende Code für den Klick-Listener sieht jetzt folgendermaßen aus:

ItemClickSupport.addTo(mRecyclerView).setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {
@Override
public void onItemClicked(RecyclerView recyclerView, int position, View v) {
    // do it
}
});

Eine kurze Erklärung zu den Klicks im RecyclerView finden Sie in diesem littlerobots_blog

3voto

Lone_iqbal Punkte 31

hier ist der vollständige Code für meinen benutzerdefinierten Adapter. Dieser Code wird die Zeilen mit den in der XML-Datei "list_item" definierten Listenelementen aufblähen und auf alle Listenelemente Zeilen mit den entsprechenden Positionen Klickereignisse ausführen.

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);

    /* hier wird list_item eine XML-Datei sein, die wir aufblähen möchten ... es ist dasselbe wie bei ListView für die Anpassung. */

        MyCustomAdapter.ViewHolder vh = new ViewHolder(v, new MyCustomAdapter.ViewHolder.onItemClickListener() {

            @Override
            public void onRecyclerItemClick(View view, int position) {
                System.out.println("Klick auf Listenelement an Position " +position);
            } 
        });
        return vh;
    }
}

3voto

Farbod Salamat-Zadeh Punkte 18863

Ich bin mir bewusst, dass es viele Antworten gibt, aber ich dachte, ich könnte auch meine Implementierung davon bereitstellen. (Weitere Details finden Sie in einer weiteren Frage, die ich beantwortet habe).

Also, um einen Klick-Listener hinzuzufügen, muss Ihre innere ViewHolder-Klasse View.OnClickListener implementieren. Das liegt daran, dass Sie einen OnClickListener auf den itemView-Parameter des Konstruktors der ViewHolder setzen. Lassen Sie mich Ihnen zeigen, was ich meine:

public class BeispielClickViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    TextView text1, text2;

    BeispielClickViewHolder(View itemView) {
        super(itemView);

        // Wir tun dies, weil wir überprüfen möchten, wann ein Element angeklickt wurde:
        itemView.setOnClickListener(this);

        // Jetzt, wie zuvor, weisen wir unsere View-Variablen zu
        text1 = (TextView) itemView.findViewById(R.id.text1);
        text2 = (TextView) itemView.findViewById(R.id.text2);
    }

    @Override
    public void onClick(View v) {
        // Der Benutzer hat möglicherweise keinen Klick-Listener für Listenelemente festgelegt, in diesem Fall wird unser Listener null sein, daher müssen wir das überprüfen
        if (mOnEntryClickListener != null) {
            mOnEntryClickListener.onEntryClick(v, getLayoutPosition());
        }
    }
}

Das Einzige, was Sie noch hinzufügen müssen, ist eine benutzerdefinierte Schnittstelle für Ihren Adapter und eine Setter-Methode:

private OnEntryClickListener mOnEntryClickListener;

public interface OnEntryClickListener {
    void onEntryClick(View view, int position);
}

public void setOnEntryClickListener(OnEntryClickListener onEntryClickListener) {
    mOnEntryClickListener = onEntryClickListener;
}

Ihr neuer, klickunterstützender Adapter ist also komplett.

Nun, lassen Sie uns ihn benutzen...

    BeispielClickAdapter clickAdapter = new BeispielClickAdapter(ihreObjekte);
    clickAdapter.setOnEntryClickListener(new BeispielClickAdapter.OnEntryClickListener() {
        @Override
        public void onEntryClick(View view, int position) {
            // Dinge, die passieren werden, wenn auf ein Listenelement geklickt wird
        }
    });

Es ist im Grunde genommen, wie Sie einen normalen Adapter einrichten würden, außer dass Sie Ihre Setter-Methode verwenden, um zu kontrollieren, was passiert, wenn der Benutzer auf ein bestimmtes Listenelement klickt.

Sie können auch durch eine Reihe von Beispielen blättern, die ich in diesem Gist auf GitHub gemacht habe:

https://gist.github.com/FarbodSalamat-Zadeh/7646564f48ee708c1582c013e1de4f07

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X