Wie kann ich ausgewählte Elemente in RecyclerView richtig hervorheben?

Lesezeit: 13 Minuten

Wie kann ich ausgewahlte Elemente in RecyclerView richtig hervorheben
Benutzer65721

Ich versuche, a zu verwenden RecyclerView als Horizontale ListView. Ich versuche herauszufinden, wie ich das ausgewählte Element hervorheben kann. Wenn ich auf eines der Elemente klicke, wird es ausgewählt und richtig hervorgehoben, aber wenn ich auf ein anderes klicke, wird das zweite mit dem älteren hervorgehoben.

Hier ist meine onClick-Funktion:

@Override
public void onClick(View view) {

    if(selectedListItem!=null){
        Log.d(TAG, "selectedListItem " + getPosition() + " " + item);
        selectedListItem.setBackgroundColor(Color.RED);
    }
    Log.d(TAG, "onClick " + getPosition() + " " + item);
    viewHolderListener.onIndexChanged(getPosition());
    selectedPosition = getPosition();
    view.setBackgroundColor(Color.CYAN); 
    selectedListItem = view;
}

Hier ist das onBindViewHolder:

@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {   
    viewHolder.setItem(fruitsData[position]);
    if(selectedPosition == position)
        viewHolder.itemView.setBackgroundColor(Color.CYAN);    
    else
        viewHolder.itemView.setBackgroundColor(Color.RED);

}

  • Die Verwendung von fokussierbaren Ansichten ist keine gute Idee, um zu versuchen, ausgewählte Elemente zu verfolgen. Überprüfen Sie meine Antwort auf eine vollständige Lösung

    – Greg Ennis

    3. März 2015 um 18:08 Uhr

  • vielleicht hilft dir das weiter amolsawant88.blogspot.in/2015/08/…

    – Amol Sawant 96 Kuli

    28. August 2015 um 8:48 Uhr

  • Recycler-Ansichtselementauswahl: stackoverflow.com/a/38501676/2648035

    – Alok Omkar

    18. März 2018 um 14:58 Uhr

  • Dies ist schwer nachzuvollziehen, wenn Sie noch nichts haben Arbeitenwas schlecht ist, da die Antworten mitlaufen und nicht viel darüber sagen, was wohin gehört.

    – Erster

    27. April 2018 um 18:08 Uhr


1646045597 621 Wie kann ich ausgewahlte Elemente in RecyclerView richtig hervorheben
zIronManBox

Dies ist ein sehr einfacher Weg, dies zu tun.

Habe einen private int selectedPos = RecyclerView.NO_POSITION; in der Klasse RecyclerView Adapter und unter der Methode onBindViewHolder Folgendes versuchen:

@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {   
    viewHolder.itemView.setSelected(selectedPos == position);

}

Und in Ihrem OnClick-Ereignis ändern Sie:

@Override
public void onClick(View view) {
     notifyItemChanged(selectedPos);
     selectedPos = getLayoutPosition();
     notifyItemChanged(selectedPos); 
}

Funktioniert wie ein Zauber für Navigional Drawer und andere RecyclerView Item Adapter.

Hinweis: Stellen Sie sicher, dass Sie in Ihrem Layout eine Hintergrundfarbe verwenden, indem Sie einen Selektor wie colabug clarified verwenden:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:drawable="@color/pressed_color" android:state_pressed="true"/>
  <item android:drawable="@color/selected_color" android:state_selected="true"/>
  <item android:drawable="@color/focused_color" android:state_focused="true"/>
</selector>

Andernfalls wird setSelected(..) nichts tun, wodurch diese Lösung unbrauchbar wird.

  • Ich habe diese Lösung mit einem Drawable/Selector-Set im Hintergrund in meiner Zeilenansicht verwendet: <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@color/pressed_color" android:state_pressed="true"/> <item android:drawable="@color/selected_color" android:state_selected="true"/> <item android:drawable="@color/focused_color" android:state_focused="true"/> </selector>

    – Colabug

    18. Januar 2016 um 12:42 Uhr


  • @zIronManBox: netter, einfacher Weg! Soll “s selectedPosition ” in der onClick-Methode “s selectedPos ” sein?

    – AJW

    8. August 2016 um 1:33 Uhr


  • getLayoutPosition() ist bei mir nicht verfügbar.

    – ka3ak

    17. März 2017 um 5:43 Uhr

  • Verwenden Sie nicht nur -1, verwenden Sie RecyclerView.NO_POSITION; (was -1 ist)

    – Martin Marconcini

    13. April 2017 um 0:45 Uhr

  • @ka3ak: getLayoutPosition ist eine Methode der ViewHolder-Klasse, deren Objekt als erster Parameter in der Bind-View-Methode übergeben wird. So kann darauf zugegriffen werden vieHolder.getLayoutPosition

    – Tushar Kathuria

    25. Mai 2017 um 16:19 Uhr

Wie kann ich ausgewahlte Elemente in RecyclerView richtig hervorheben
Triff Vora

AKTUALISIEREN [26/Jul/2017]:

Wie der Pawan im Kommentar zu dieser IDE-Warnung erwähnt hat, diese feste Position nicht zu verwenden, habe ich meinen Code gerade wie folgt geändert. Der Klick-Listener wird verschoben ViewHolderund dort bekomme ich die Position mit getAdapterPosition() Methode

int selected_position = 0; // You have to set this globally in the Adapter class

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    Item item = items.get(position);

    // Here I am just highlighting the background
    holder.itemView.setBackgroundColor(selected_position == position ? Color.GREEN : Color.TRANSPARENT);
}

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

    public ViewHolder(View itemView) {
        super(itemView);
        itemView.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        // Below line is just like a safety check, because sometimes holder could be null,
        // in that case, getAdapterPosition() will return RecyclerView.NO_POSITION
        if (getAdapterPosition() == RecyclerView.NO_POSITION) return;

        // Updating old as well as new positions
        notifyItemChanged(selected_position);
        selected_position = getAdapterPosition();
        notifyItemChanged(selected_position);

        // Do your another stuff for your onClick
    }
}

hoffe das hilft.

  • Das ist großartig! Ich bin jedoch etwas verwirrt. Können Sie mir helfen, eine Möglichkeit zu implementieren und diese Antwort zu erweitern, wie Sie das tun, was Sie in der Else-Anweisung tun, wenn Sie auf ein bereits ausgewähltes Element klicken, damit Sie es abwählen: sonst { holder.itemView.setBackgroundColor(Color.TRANSPARENT); }

    – iBobb

    27. Februar 2016 um 14:20 Uhr

  • Natürlich ja. @iBobb. Für NICHT AUSGEWÄHLTE Elemente, dh deren Position nicht gleich unserer ‘ausgewählten_position’-Variablen ist, wird KEIN Hintergrund angezeigt. Ich habe dies verwendet, weil RecyclerView, wie der Name schon sagt, jedes Element recycelt, also einen GRÜNEN Hintergrund für zufällige Zeilen setzt, während wir SCROLLEN, deshalb habe ich diesen ELSE-Teil platziert. (Sie können es einfach ausprobieren, indem Sie diesen ELSE-Teil auskommentieren und dann in Ihrer Recycler-Ansicht scrollen.)

    – Treffen Sie Vora

    28. Februar 2016 um 11:57 Uhr


  • Ich glaube du hast meine Frage nicht verstanden. Sie wissen in jeder App, wenn Sie etwas auswählen, wird es hervorgehoben. Wenn Sie es erneut halten, wird es deaktiviert. Wie würden wir das umsetzen? Im Moment können wir nur mit Ihrem Code auswählen und das Berühren und Halten desselben Elements bewirkt nichts.

    – iBobb

    28. Februar 2016 um 14:17 Uhr

  • Es kann möglich sein, aber dafür müssen Sie onLongClickListener anstelle von onClickListener überschreiben, im Moment bin ich beschäftigt, also kann ich keinen vollständigen Code bereitstellen, aber Sie sollten es im Grunde so tun.

    – Treffen Sie Vora

    1. März 2016 um 12:42 Uhr

  • Gute Arbeit Treffen. Für NICHT AUSGEWÄHLT hier die Codes unten, es funktioniert für mich, int previouss selectedPosition = -2; // global gesetzt. dann kommen nach diesen Zeilen notificationItemChanged(s selected_position); Fügen Sie die folgenden Zeilen hinzu, wenn (vorherige ausgewählte Position == ausgewählte_position) { ausgewählte_position = -1; benachrichtigenItemChanged (ausgewählte_position); } Else {vorherigeausgewähltePosition = ausgewählte_Position; } Probieren Sie dieses aus, es wird funktionieren.

    – GNSRIDHAR

    27. April 2020 um 9:26 Uhr


Wie kann ich ausgewahlte Elemente in RecyclerView richtig hervorheben
Gregor Ennis

Ich habe eine Basisadapterklasse geschrieben, um die Elementauswahl automatisch mit einer RecyclerView zu handhaben. Leiten Sie einfach Ihren Adapter davon ab und verwenden Sie darstellbare Zustandslisten mit state_selected, wie Sie es mit einer Listenansicht tun würden.

Ich habe ein Blogbeitrag hier darüber, aber hier ist der Code:

public abstract class TrackSelectionAdapter<VH extends TrackSelectionAdapter.ViewHolder> extends RecyclerView.Adapter<VH> {
    // Start with first item selected
    private int focusedItem = 0;

    @Override
    public void onAttachedToRecyclerView(final RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);

        // Handle key up and key down and attempt to move selection
        recyclerView.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                RecyclerView.LayoutManager lm = recyclerView.getLayoutManager();

                // Return false if scrolled to the bounds and allow focus to move off the list
                if (event.getAction() == KeyEvent.ACTION_DOWN) {
                    if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
                        return tryMoveSelection(lm, 1);
                    } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
                        return tryMoveSelection(lm, -1);
                    }
                }

                return false;
            }
        });
    }

    private boolean tryMoveSelection(RecyclerView.LayoutManager lm, int direction) {
        int tryFocusItem = focusedItem + direction;

        // If still within valid bounds, move the selection, notify to redraw, and scroll
        if (tryFocusItem >= 0 && tryFocusItem < getItemCount()) {
            notifyItemChanged(focusedItem);
            focusedItem = tryFocusItem;
            notifyItemChanged(focusedItem);
            lm.scrollToPosition(focusedItem);
            return true;
        }

        return false;
    }

    @Override
    public void onBindViewHolder(VH viewHolder, int i) {
        // Set selected state; use a state list drawable to style the view
        viewHolder.itemView.setSelected(focusedItem == i);
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        public ViewHolder(View itemView) {
            super(itemView);

            // Handle item click and set the selection
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // Redraw the old selection and the new
                    notifyItemChanged(focusedItem);
                    focusedItem = getLayoutPosition();
                    notifyItemChanged(focusedItem);
                }
            });
        }
    }
} 

  • mRecyclerView ist nirgendwo deklariert. Sollen wir es einfach als Parameter im Konstruktor übergeben und in einem Feld speichern?

    – Pedro

    26. März 2015 um 0:13 Uhr


  • Das tut mir leid. Mein Adapter ist eine innere Klasse meines Fragments, sodass er Zugriff auf das Recycler-Ansichtsfeld hat. Ansonsten ja, Sie könnten es als Parameter übergeben. Oder noch besser Griff onRecyclerViewAttached und dort in einer Member-Variablen speichern.

    – Greg Ennis

    26. März 2015 um 12:54 Uhr

  • Gute Antwort, aber warum getChildPosition() verwenden? Es gibt eine andere Methode developer.android.com/reference/android/support/v7/widget/…

    – skyfishjy

    15. April 2015 um 10:03 Uhr

  • Es tut mir leid, meinst du, ich muss nur deine importieren TrackSelectionAdapter Klasse und in meiner Liste verwenden? Wie leite ich meinen Adapter von Ihrer Klasse ab? Könnten Sie bitte auf meine Frage antworten? Ich stecke so tief fest: stackoverflow.com/questions/29695811/…

    – Kris

    17. April 2015 um 18:22 Uhr


  • Ich habe dies ausprobiert und festgestellt, dass die beiden aufeinanderfolgenden Aufrufe von NotifyItemChanged() jeden Anschein von reibungslosem Scrollen auf langsamerer Hardware zunichte gemacht haben. War auf dem Fire TV vor dem Lollipop-Update besonders schlimm

    – Rotes Shirt

    18. April 2016 um 17:30 Uhr

1646045601 642 Wie kann ich ausgewahlte Elemente in RecyclerView richtig hervorheben
Entitäten

Wie in dieser verknüpften Frage erwähnt, sollte das Festlegen von Listenern für viewHolders in onCreateViewHolder erfolgen. Allerdings zielte die folgende Implementierung ursprünglich auf Mehrfachauswahl ab, aber ich habe einen Hack in das Snippet geworfen, um eine Einzelauswahl zu erzwingen.(*1)

// an array of selected items (Integer indices) 
private final ArrayList<Integer> selected = new ArrayList<>();

// items coming into view
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
    // each time an item comes into view, its position is checked
    // against "selected" indices
    if (!selected.contains(position)){
        // view not selected
        holder.parent.setBackgroundColor(Color.LTGRAY);
    }
    else
        // view is selected
        holder.parent.setBackgroundColor(Color.CYAN);
}

// selecting items
@Override
public boolean onLongClick(View v) {
        
        // select (set color) immediately.
        v.setBackgroundColor(Color.CYAN);

        // (*1)
        // forcing single selection here...
        if (selected.isEmpty()){
            selected.add(position); // (done - see note)
        }else {
            int oldSelected = selected.get(0);
            selected.clear(); // (*1)... and here.
            selected.add(position);
            // note: We do not notify that an item has been selected
            // because that work is done here.  We instead send
            // notifications for items which have been deselected.
            notifyItemChanged(oldSelected);
        }
        return false;
}

1646045602 714 Wie kann ich ausgewahlte Elemente in RecyclerView richtig hervorheben
Davideas

Ich denke, ich habe das beste Tutorial zur Verwendung von RecyclerView mit allen grundlegenden Funktionen gefunden, die wir benötigen (Einzel- und Mehrfachauswahl, Hervorheben, Ripple, Klicken und Entfernen in Mehrfachauswahl usw.).

Hier ist es –> http://enoent.fr/blog/2015/01/18/recyclerview-basics/

Darauf aufbauend konnte ich eine Bibliothek „FlexibleAdapter“ erstellen, die einen SelectableAdapter erweitert. Ich denke, dies muss in der Verantwortung des Adapters liegen, eigentlich müssen Sie die grundlegenden Funktionen des Adapters nicht jedes Mal neu schreiben, sondern eine Bibliothek dies tun lassen, sodass Sie einfach dieselbe Implementierung wiederverwenden können.

Dieser Adapter ist sehr schnell, er funktioniert sofort nach dem Auspacken (Sie müssen ihn nicht verlängern); Sie passen die Elemente für alle Ansichtstypen an, die Sie benötigen. ViewHolder sind vordefiniert: allgemeine Ereignisse sind bereits implementiert: einfacher und langer Klick; es behält den Zustand nach der Rotation bei und viel viel mehr.

Bitte schauen Sie es sich an und setzen Sie es gerne in Ihren Projekten ein.

https://github.com/davideas/FlexibleAdapter

Ein Wiki ist ebenfalls verfügbar.

  • Tolle Arbeit, diesen Adapter zu schreiben, er scheint sehr nützlich zu sein. Die einzige Sache ist, dass es wirklich einige grundlegende Beispiele und Dokumentation braucht, ich finde es ein wenig verwirrend, es überhaupt zum Laufen zu bringen. Potenziell großartig!

    – Voy

    20. Juni 2016 um 10:17 Uhr

  • Ja, ich habe dort nicht genügend Informationen gefunden, um loszulegen. API-Referenz konnte nicht gefunden werden, obwohl der Code in diesem Sinne kommentiert zu sein scheint. Die Beispiel-App scheint – obwohl breit und informativ – ohne Vorkenntnisse der Bibliothek sehr schwer zu verstehen. Alle Anwendungsfälle sind miteinander verbunden, es gibt kaum Hinweise darauf, was was demonstriert, Klassen werden in verschiedenen Szenarien wiederverwendet, was dazu führt, dass sie mit Informationen überladen werden. Ich habe hier ein neues Problem mit diesen Vorschlägen erstellt: github.com/davideas/FlexibleAdapter/issues/120

    – Voy

    22. Juni 2016 um 9:37 Uhr

  • Wiki wurde komplett neu geschrieben und steht kurz vor der Fertigstellung.

    – Davideas

    6. Juni 2017 um 13:23 Uhr

Schau dir meine Lösung an. Ich nehme an, dass Sie die ausgewählte Position im Halter festlegen und als Tag of View übergeben sollten. Die Ansicht sollte in der Methode onCreateViewHolder(…) gesetzt werden. Es gibt auch den richtigen Ort, um Listener für die Ansicht festzulegen, z. B. OnClickListener oder LongClickListener.

Bitte schauen Sie sich das Beispiel unten an und lesen Sie die Kommentare zum Code.

public class MyListAdapter extends RecyclerView.Adapter<MyListAdapter.ViewHolder> {
    //Here is current selection position
    private int mSelectedPosition = 0;
    private OnMyListItemClick mOnMainMenuClickListener = OnMyListItemClick.NULL;

    ...

    // constructor, method which allow to set list yourObjectList

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //here you prepare your view 
        // inflate it
        // set listener for it
        final ViewHolder result = new ViewHolder(view);
        final View view =  LayoutInflater.from(parent.getContext()).inflate(R.layout.your_view_layout, parent, false);
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //here you set your current position from holder of clicked view
                mSelectedPosition = result.getAdapterPosition();

                //here you pass object from your list - item value which you clicked
                mOnMainMenuClickListener.onMyListItemClick(yourObjectList.get(mSelectedPosition));

                //here you inform view that something was change - view will be invalidated
                notifyDataSetChanged();
            }
        });
        return result;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        final YourObject yourObject = yourObjectList.get(position);

        holder.bind(yourObject);
        if(mSelectedPosition == position)
            holder.itemView.setBackgroundColor(Color.CYAN);
        else
            holder.itemView.setBackgroundColor(Color.RED);
    }

    // you can create your own listener which you set for adapter
    public void setOnMainMenuClickListener(OnMyListItemClick onMyListItemClick) {
        mOnMainMenuClickListener = onMyListItemClick == null ? OnMyListItemClick.NULL : onMyListItemClick;
    }

    static class ViewHolder extends RecyclerView.ViewHolder {


        ViewHolder(View view) {
            super(view);
        }

        private void bind(YourObject object){
            //bind view with yourObject
        }
    }

    public interface OnMyListItemClick {
        OnMyListItemClick NULL = new OnMyListItemClick() {
            @Override
            public void onMyListItemClick(YourObject item) {

            }
        };

        void onMyListItemClick(YourObject item);
    }
}

  • Tolle Arbeit, diesen Adapter zu schreiben, er scheint sehr nützlich zu sein. Die einzige Sache ist, dass es wirklich einige grundlegende Beispiele und Dokumentation braucht, ich finde es ein wenig verwirrend, es überhaupt zum Laufen zu bringen. Potenziell großartig!

    – Voy

    20. Juni 2016 um 10:17 Uhr

  • Ja, ich habe dort nicht genügend Informationen gefunden, um loszulegen. API-Referenz konnte nicht gefunden werden, obwohl der Code in diesem Sinne kommentiert zu sein scheint. Die Beispiel-App scheint – obwohl breit und informativ – ohne Vorkenntnisse der Bibliothek sehr schwer zu verstehen. Alle Anwendungsfälle sind miteinander verbunden, es gibt kaum Hinweise darauf, was was demonstriert, Klassen werden in verschiedenen Szenarien wiederverwendet, was dazu führt, dass sie mit Informationen überladen werden. Ich habe hier ein neues Problem mit diesen Vorschlägen erstellt: github.com/davideas/FlexibleAdapter/issues/120

    – Voy

    22. Juni 2016 um 9:37 Uhr

  • Wiki wurde komplett neu geschrieben und steht kurz vor der Fertigstellung.

    – Davideas

    6. Juni 2017 um 13:23 Uhr

1646045603 354 Wie kann ich ausgewahlte Elemente in RecyclerView richtig hervorheben
amodkanthe

Es gibt keinen Selektor in RecyclerView wie ListView und GridView, aber Sie versuchen unten, was für mich funktioniert hat

Erstellen Sie wie unten eine zeichnerische Auswahl

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"> 
<item android:state_pressed="true">
   <shape>
         <solid android:color="@color/blue" />
   </shape>
</item>

<item android:state_pressed="false">
    <shape>
       <solid android:color="@android:color/transparent" />
    </shape>
</item>
</selector>

Legen Sie dann dieses Drawable als Hintergrund Ihres RecyclerView-Zeilenlayouts fest

android:background="@drawable/selector"

  • Das bringt nichts Nützliches. Es ändert nur die Farbe während der Druckzeit.

    – Leonid Ustenko

    12. Oktober 2016 um 10:00 Uhr

887450cookie-checkWie kann ich ausgewählte Elemente in RecyclerView richtig hervorheben?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy