RecyclerView ambiguos setVisibility-Funktion, Klick auf eine Ansicht wirkt sich auf mehrere Ansichten aus

Dies ist das Projekt, das ich versuche zu laufen. Hier ist mein Code für den onBindViewHolder aus der RecyclerView.Adapter Klasse

@Override public void onBindViewHolder(ViewHolder holder, final int position) { TextView title = (TextView) holder.view.findViewById(R.id.title); final TextView desc = (TextView) holder.view.findViewById(R.id.desc); final ImageView imageView = (ImageView) holder.view.findViewById(R.id.imageView); title.setText(pojos.get(position).getTitle()); desc.setText(pojos.get(position).getDesc()); imageView.setImageResource(pojos.get(position).getImage()); imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { desc.setText("clicked"); desc.setBackgroundColor(Color.BLUE); imageView.setImageResource(R.drawable.heart_red); } }); } 

Die Liste lädt gut, das Problem passiert, wenn der imageView's onclicklistener aufgerufen wird.

 desc.setText("clicked"); 

Die obige Zeile macht die Änderung in der Liste, auf die sie geklickt wurde. aber

  desc.setBackgroundColor(Color.BLUE); 

Wenn diese Zeile ausgeführt wird, wird die Änderung in mehreren Elementen in der Liste angezeigt. Was geht falsch In den unten gezeigten Bildern klickte ich auf Punkt 0, der Text ändert sich auf "geklickt" und die Farbe ist eingestellt. Aber wenn ich nach unten blättere, ist auch Punkt 12 von meinem Klick auf Punkt 0 betroffen. Nur die Hintergrundfarbenänderung hat sich reflektiert, nicht der Textwechsel. Wie kann ich das stoppen?

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

Ich habe versucht, dies für eine lange Zeit zu lösen, bitte laden Sie das Projekt und versuchen, den Code auszuführen, um zu verstehen, was ich genau meine, wenn meine Frage ist nicht klar.

  • Android ListView Zeilen in ScrollView nicht vollständig angezeigt - abgeschnitten
  • Android Html.fromHtml (String) funktioniert nicht für <font color = '#'> text </ font>
  • Gibt es einen einfacheren / besseren Weg, um eine Grenze / Umrisse um meine TextView zu setzen?
  • Wie kann ich einen Klick auf den ActionBar-Titel erkennen?
  • Wie kann man TextView um ein ImageView ausrichten?
  • Problem bei der Verwendung einer benutzerdefinierten Schriftart - "native Schrift kann nicht gemacht werden"
  • Android setzt die Schwerkraft für eine TextView programmgesteuert ein
  • Anzeigen einer MS Word-Datei in View (sagen TextView) in Android
  • 5 Solutions collect form web for “RecyclerView ambiguos setVisibility-Funktion, Klick auf eine Ansicht wirkt sich auf mehrere Ansichten aus”

    Dies geschieht, weil die Ansichten recycelt und wiederverwendet werden.

    Wenn also die Aussicht recycelt wird, behält sie die Eigenschaften der "alten" Ansicht, wenn man sie nicht wieder ändert. Wenn Sie also auf die Nummer 12 blättern, wird die Ansicht, die die Nummer 1 verwendet hat, recycelt (da sie nicht mehr auf dem Bildschirm zu sehen ist) und wird verwendet, um die Nummer 12 zu erstellen. Deshalb ist die blaue Farbe auf Nummer 12

    Wenn das Element zum Beispiel angeklickt wird, müssen Sie einen "geklickten" Wert in Ihr POJO-Objekt speichern. Dann, wenn das Element gezeichnet wird, überprüfen Sie diesen Wert und legen Sie die richtige Bild- / Hintergrundfarbe abhängig von diesem Wert.

    Ich habe dies in der unten genannten Code getan, so sollte es Ihnen eine grobe Vorstellung davon, was zu tun:

     @Override public void onBindViewHolder(ViewHolder holder, final int position) { TextView title = (TextView) holder.view.findViewById(R.id.title); final TextView desc = (TextView) holder.view.findViewById(R.id.desc); final ImageView imageView = (ImageView) holder.view.findViewById(R.id.imageView); final MyPojo pojo = pojos.get(position); title.setText(pojo.getTitle()); if(!pojo.clicked) { desc.setText(pojo.getDesc()); imageView.setImageResource(pojo.getImage()); desc.setBackgroundColor(Color.argb(0,0,0,0)); } else { desc.setText("clicked"); desc.setBackgroundColor(Color.BLUE); imageView.setImageResource(R.drawable.heart_red); } imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { pojo.clicked = true; desc.setText("clicked"); desc.setBackgroundColor(Color.BLUE); imageView.setImageResource(R.drawable.heart_red); } }); } 

    Und ich habe eine "geklickte" Boolesche zur MyPojo-Klasse hinzugefügt.

     public class MyPojo { String title; String desc; int image; boolean clicked; } 

    Füge einfach eine Methode in deiner Adapterklasse nach der Methode getItemCount hinzu

     @Override public int getItemViewType(int position) { return position; } 

    Es wird das Problem lösen

    Es scheint, dass Sie eine Verwirrung bei der Verwendung von RecyclerView haben, indem Sie auf findViewById in onBindViewHolder aufrufen. Diese teuren Lookups sollten in onCreateViewHolder passieren, wo Sie alle Ansichten nachschlagen und ihre Referenzen auf Ihren benutzerdefinierten View-Inhaber speichern. Ich ging voran auf Ihren Code in github repo und schlagen die folgenden Änderungen vor:

     public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { private ArrayList<MyPojo> pojos; // Provide a reference to the views for each data item // Complex data items may need more than one view per item, and // you provide access to all the views for a data item in a view holder public static class ViewHolder extends RecyclerView.ViewHolder { // each data item is just a string in this case public TextView title; public TextView desc; public ImageView imageView; public ViewHolder(View v) { super(v); // all expensive findViewById lookups happen in ViewHolder constructor, // which is called only when onCreateViewHolder is called this.title = (TextView) v.findViewById(R.id.title); this.desc = (TextView) v.findViewById(R.id.desc); this.imageView = (ImageView) v.findViewById(R.id.imageView); } } // Provide a suitable constructor (depends on the kind of dataset) public MyAdapter(ArrayList<MyPojo> pojos) { this.pojos = pojos; } // Create new views (invoked by the layout manager) @Override public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { // create a new view View v = LayoutInflater.from(parent.getContext()) .inflate(R.layout.row, parent, false); // set the view's size, margins, paddings and layout parameters ViewHolder vh = new ViewHolder(v); return vh; } // Replace the contents of a view (invoked by the layout manager) @Override public void onBindViewHolder(ViewHolder holder, final int position) { // this callback will be constantly called during scrolling // therefore, to make it smooth, we should not make any expensive operations here // - get element from your dataset at this position // - replace the contents of the view with that element holder.title.setText(pojos.get(position).getTitle()); holder.desc.setText(pojos.get(position).getDesc()); holder.imageView.setImageResource(pojos.get(position).getImage()); // you'll need to implement this function based on the way you decide to save clicked state for each clicked view if(isClickedState(position)) { holder.imageView.setImageResource(R.drawable.heart_red); } else { // provide some default background holder.imageView.setImageResource(R.drawable.default); } holder.imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // you'll need to implement this function to save clicked position saveClickForPosition(position) imageView.setImageResource(R.drawable.heart_red); } }); } // Return the size of your dataset (invoked by the layout manager) @Override public int getItemCount() { return pojos.size(); } } 

    Dies sollte der Ausgangspunkt für Ihr Debugging sein, da dieses Muster ein ordnungsgemäßes Recycling garantiert.

    Wie es auch in einer anderen Antwort erwähnt wird, müssen Sie sich an den angeklickten Zustand für jedes Element erinnern, und diesen Zustand in MyPojo Objekt oder irgendwo anders zu halten sollte relativ einfach zu erreichen sein.

    Ich hatte ein ähnliches Problem, (hatte eine Anzahl Änderung auf mehrere Listenelemente anstelle von nur einem). Ich nehme an, weil, wie eine Recycling-Ansicht funktioniert, konnte ich es reparieren, indem ich alles, was ich beabsichtigte, zu ändern, was auch immer ich will, dass der Standard ist.

    IE: Wenn du den Hintergrund auf Blau umstellen möchtest, wenn du die Liste lasst, setze die, die nicht blau bis grau sein soll (oder was auch immer du willst).

    Also hier:

     ViewHolder vh = new ViewHolder(v); return vh; 

    Sie möchten die Vorgaben angeben

    Hier versuchen, diesen Adapter zu benutzen:

     public class myAdapter extends RecyclerView.Adapter<CopyOfConversationAdapter.ViewHolder> { private ArrayList<conversationItem> pojos; // inner class to hold a reference to each item of RecyclerView public static class ViewHolder extends RecyclerView.ViewHolder { TextView title; TextView desc; ImageView imageView; public ViewHolder(View itemLayoutView) { super(itemLayoutView); title= (TextView) itemLayoutView.findViewById(R.id.title); desc= (TextView) itemLayoutView.findViewById(R.id.desc); imageView= (ImageView) itemLayoutView.findViewById(R.id.imageView); } } // Return the size of your itemsData (invoked by the layout manager) @Override public int getItemCount() { return pojos.size(); } public CopyOfConversationAdapter(Pojos[] pojos) { this.pojos = new ArrayList<conversationItem>(); this.pojos.addAll(Arrays.asList(Items)); } // Create new views (invoked by the layout manager) @Override public CopyOfConversationAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { // create a new view View itemLayoutView; itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.comments_item_layout_, null); ViewHolder viewHolder = new ViewHolder(itemLayoutView); return viewHolder; } // Replace the contents of a view (invoked by the layout manager) @Override public void onBindViewHolder(ViewHolder viewHolder, final int position) { // - get data from your itemsData at this position // - replace the contents of the view with that itemsData viewHolder.title.setText(pojos.get(position).getSender()); viewHolder.desc.setText(pojos.get(position).getSnippet()); viewHolder.imageView.setText(pojos.get(position).getIcon()); viewHolder.imageView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub desc.setText("clicked"); desc.setBackgroundColor(Color.BLUE); imageView.setImageResource(R.drawable.heart_red); } }); } 

    }

    Das Android ist ein Google Android Fan-Website, Alles ├╝ber Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.