ListView ist bereits in der Lage, sich selbst so zu messen, dass es groß genug ist, um alle Elemente anzuzeigen. Dies ist jedoch nicht der Fall, wenn Sie einfach wrap_content (MeasureSpec.UNSPECIFIED) angeben. Dies geschieht, wenn mit MeasureSpec.AT_MOST eine Höhe angegeben wird. Mit diesem Wissen können Sie eine sehr einfache Unterklasse erstellen, um dieses Problem zu lösen, die weitaus besser funktioniert als alle oben genannten Lösungen. Sie sollten für diese Unterklasse weiterhin wrap_content verwenden.
public class ListViewForEmbeddingInScrollView extends ListView {
public ListViewForEmbeddingInScrollView(Context context) {
super(context);
}
public ListViewForEmbeddingInScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ListViewForEmbeddingInScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 4, MeasureSpec.AT_MOST));
}
}
Wenn Sie die heightMeasureSpec so bearbeiten, dass sie AT_MOST mit einer sehr großen Größe (Integer.MAX_VALUE >> 4) ist, misst die ListView alle untergeordneten Elemente bis zur angegebenen (sehr großen) Höhe und stellt ihre Höhe entsprechend ein.
Dies funktioniert aus mehreren Gründen besser als die anderen Lösungen:
- Es misst alles richtig (Polsterung, Trennwände)
- Es misst die ListView während des Messdurchlaufs
- Aufgrund von # 2 werden Änderungen in der Breite oder Anzahl der Elemente ohne zusätzlichen Code korrekt behandelt
Auf der anderen Seite könnte man argumentieren, dass dies auf undokumentiertem Verhalten im SDK beruht, das sich ändern könnte. Auf der anderen Seite könnten Sie argumentieren, dass wrap_content auf diese Weise wirklich mit ListView funktionieren sollte und dass das aktuelle Verhalten von wrap_content nur fehlerhaft ist.
Wenn Sie befürchten, dass sich das Verhalten in Zukunft ändern könnte, sollten Sie einfach die Funktion onMeasure und die zugehörigen Funktionen aus ListView.java in Ihre eigene Unterklasse kopieren und dann den Pfad AT_MOST durch onMeasure auch für UNSPECIFIED ausführen.
Übrigens glaube ich, dass dies ein absolut gültiger Ansatz ist, wenn Sie mit einer kleinen Anzahl von Listenelementen arbeiten. Es mag im Vergleich zu LinearLayout ineffizient sein, aber wenn die Anzahl der Elemente gering ist, ist die Verwendung von LinearLayout eine unnötige Optimierung und daher unnötige Komplexität.