Also habe ich dieses Problem hatte ich vor, und natürlich bat ich um Hilfe zu hier . Die Antwort von Luksprog war großartig, da ich keine Ahnung hatte, wie sich ListView und GridView durch das Recycling von Views optimiert haben. Mit seinem Rat konnte ich also ändern, wie ich meinem GridView Ansichten hinzufügte. Das Problem ist jetzt, dass ich etwas habe, das keinen Sinn ergibt. Das ist mein getView
von meinem BaseAdapter
:
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
convertView = inflater.inflate(R.layout.day_view_item, parent, false);
}
Log.d("DayViewActivity", "Position is: "+position);
((TextView)convertView.findViewById(R.id.day_hour_side)).setText(array[position]);
LinearLayout layout = (LinearLayout)convertView.findViewById(R.id.day_event_layout);
//layout.addView(new EventFrame(parent.getContext()));
TextView create = new TextView(DayViewActivity.this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 62, getResources().getDisplayMetrics()), 1.0f);
params.topMargin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics());
params.bottomMargin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics());
create.setLayoutParams(params);
create.setBackgroundColor(Color.BLUE);
create.setText("Test");
//the following is my original LinearLayout.LayoutParams for correctly setting the TextView Height
//new LinearLayout.LayoutParams(0, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, getResources().getDisplayMetrics()), 1.0f)
if(position == 0) {
Log.d("DayViewActivity", "This should only be running when position is 0. The position is: "+position);
layout.addView(create);
}
return convertView;
}
}
Das Problem ist, wenn ich scrolle, passiert dies und nicht auf Position 0 ... Sieht aus wie Position 6 und Position 8, und es bringt zwei auf Position 8. Jetzt versuche ich immer noch, den Dreh raus zu bekommen, ListView und GridView zu verwenden, so wie ich es tue Ich verstehe nicht, warum das passiert. Einer der Hauptgründe, warum ich diese Frage stelle, besteht darin, anderen zu helfen, die wahrscheinlich nichts über ListView und GridViews Recycling-Ansicht oder den ScrapView-Mechanismus in diesem Artikel wissen.
Später bearbeiten
Hinzufügen eines Links zu einem Google IO-Vortrag, der im Grunde alles ist, was Sie brauchen, um zu verstehen, wie ListView funktioniert. Link war in einem der Kommentare tot. User3427079 war also nett genug, um diesen Link zu aktualisieren. Hier ist es für den einfachen Zugang.
0
) , rückgängig zu machen .ListView
eine neue Zeile angezeigt werden muss (z. B. weiter nach unten / oben scrollen). Das Problem ist, dass die Ansicht, die gerade verschwunden ist und an zukünftigen benötigten Positionen verwendet wird,TextView
bereits hinzugefügt wurde. Dies ist das Problem. Um es zu lösen, müssen Sie es in dergetView
Methode entfernen , wenn diegetView
Methode für eine andere Position als aufgerufen wird0
.Antworten:
Anfangs war mir auch das Recycling von Listenansichten und der Mechanismus zur Verwendung von Konvertierungsansichten nicht bekannt, aber nach ein paar Tagen Recherche verstehe ich die Mechanismen der Listenansicht ziemlich gut, indem ich mich auf ein Bild aus android.amberfog beziehe
Immer wenn Ihre Listenansicht von einem Adapter gefüllt wird, wird im Grunde die Anzahl der Zeilen angezeigt, die die Listenansicht auf dem Bildschirm anzeigen kann, und die Anzahl der Zeilen erhöht sich nicht, selbst wenn Sie durch die Liste scrollen. Dies ist der Trick, den Android verwendet, damit die Listenansicht effizienter und schneller funktioniert. Wie Sie sehen können, enthält die Listenansicht, die sich auf das Bild bezieht, zunächst 7 sichtbare Elemente. Wenn Sie nach oben scrollen, bis Element 1 nicht mehr sichtbar ist, übergibt getView () diese Ansicht (dh Element1) an das Recycler und Sie können verwenden
in deinem
Sie werden in Ihrem Logcat feststellen, dass die Konvertierungsansicht zunächst für alle sichtbaren Zeilen null ist, da im Recycler anfangs keine Ansichten (dh Elemente) vorhanden waren. Daher erstellt getView () für jedes der sichtbaren Elemente eine neue Ansicht, jedoch für die Sobald Sie nach oben scrollen und Element 1 den Bildschirm verlässt, wird es mit seinem aktuellen Status an den Recycler gesendet (z. B. der TextView-Text oder in meinem Fall, wenn das Kontrollkästchen aktiviert ist, wird es der Ansicht und zugeordnet im Recycler gelagert).
Wenn Sie jetzt nach oben / unten scrollen, erstellt Ihre Listenansicht keine neue Ansicht, sondern verwendet die Ansicht in Ihrem Recycler. In Ihrem Logcat werden Sie feststellen, dass die 'convertView' nicht null ist, da Ihr neues Element 8 mit convertview gezeichnet wird, dh im Grunde genommen nimmt es die Ansicht von Element 1 vom Recycler und bläst Element 8 an seiner Stelle auf, und Sie können beobachten das in meinem Code. Wenn Sie ein Kontrollkästchen hatten und es an Position 0 aktiviert haben (sagen wir, Element1 hatte ein Kontrollkästchen und Sie haben es aktiviert). Wenn Sie also nach unten scrollen, wird das Kontrollkästchen für Element 8 bereits aktiviert. Aus diesem Grund verwendet die Listenansicht dieselbe Ansicht. Aufgrund der Leistungsoptimierung wird kein neues für Sie erstellt.
Wichtige Dinge
1 . Stellen Sie das
layout_height
undlayout_width
Ihrer Listenansicht niemalswrap_content
sogetView()
ein, dass Ihr Adapter gezwungen wird, ein untergeordnetes Element zum Messen der Höhe der in der Listenansicht zu zeichnenden Ansichten zu erhalten. Dies kann zu unerwartetem Verhalten wie der Rückgabe der Konvertierungsansicht führen, auch wenn die Liste nicht gescrollt wird. Immer verwendenmatch_parent
oder korrigieren Breite Höhe.2 . Wenn Sie ein Layout oder eine Ansicht verwenden möchten, nachdem Ihre Listenansicht und Ihre Frage in den Sinn gekommen sind, wenn ich die Ansicht
layout_height
auffill_parent
die Ansicht eingestellt habe , wird die Listenansicht nicht angezeigt, wenn sie auf dem Bildschirm angezeigt wird. Daher ist es besser, Ihre Listenansicht in eine zu setzen Zum Beispiel Lineares Layout und stellen Sie die Höhe und Breite dieses Layouts gemäß Ihren Anforderungen ein und ändern Sie das Attribut für Höhe und Breite Ihrer Listenansicht ab Ihrem Layout (z. B. wenn Ihre Layoutbreite 320 und die Höhe 280 beträgt ) und dann Ihre Listenansicht sollte die gleiche Höhe und Breite haben. Dies teilt getView () die genaue Höhe und Breite der zu rendernden Ansichten mit, und getView () ruft nicht immer wieder zufällige Zeilen auf, und andere Probleme wie das Zurückgeben der Konvertierungsansicht, noch bevor das Scrollen nicht auftritt, habe ich getestet dies selbst, es sei denn, meine Listenansicht befand sich im lineaLayout, es gab auch Probleme wie das Wiederholen des Aufrufs der Ansicht und das Konvertieren der Ansicht als, das Einfügen der Listenansicht in das LinearLayout funktionierte für mich wie Zauberei (wusste nicht warum)Aber jetzt ist es gelöst, ich weiß, ich kann es nicht so gut erklären, aber da ich meinen ganzen Tag damit verbracht habe, es zu verstehen, dachte ich, dass andere Anfänger wie ich Hilfe von meiner Erfahrung bekommen können und ich hoffe, dass ihr jetzt ein bisschen Verständnis habt des ListView- Frameworks, wie es funktioniert, da es wirklich chaotisch und knifflig ist, so dass Anfänger zu viele Probleme beim Verstehen hatten
quelle
if you had a checkbox and if you check it at position 0(let say item1 has also a checkbox and you checked it) so when you scroll down you will see item 8 checkbox is already checked,this is why listview is re using the same view not creating a new for you due to performance optimization.
damit ich meinen Fehler erkannte. Bester Beitrag über Android ListView Recycling, auf den ich gestoßen bin!RecyclerView
auch mit dem gleichen Mechanismus funktioniert. In meiner Frage stackoverflow.com/questions/47897770/… weiß ich , dass die Aufgabe mit ziemlich unmöglich istlistView
. Soll ich es versuchenrecyclerView
?Achten Sie im Holder-Muster darauf, dass Sie die Position in Ihrem Holder-Objekt jedes Mal festlegen, zum Beispiel:
Dies ist ein Beispiel aus einer abstrakten Klasse, in der
führt alle Einstellvorgänge für die aus
quelle
parent.setTag(holder);
anstelle des richtigen Weges, der ist,view.setTag(holder);
Mit dem Halter-Muster können Sie erreichen, was Sie wollen:
Eine Beschreibung dieses Musters finden Sie hier:
Das Recycling der Listenansicht erfolgt, wenn Sie auf dem Bildschirm nach unten scrollen und die obigen Listenansichtselemente ausgeblendet sind. Sie werden wiederverwendet, um neue Listenansichtselemente anzuzeigen.
quelle