ListView może już mierzyć swoją wysokość, aby wyświetlić wszystkie elementy, ale nie robi tego, gdy po prostu określisz wrap_content (MeasureSpec.UNSPECIFIED). Zrobi to, gdy otrzyma wysokość z MeasureSpec.AT_MOST. Dzięki tej wiedzy możesz utworzyć bardzo prostą podklasę, aby rozwiązać ten problem, który działa o wiele lepiej niż którekolwiek z powyższych rozwiązań. Nadal powinieneś używać wrap_content z tą podklasą.
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));
}
}
Manipulowanie heightMeasureSpec o wartości AT_MOST o bardzo dużym rozmiarze (Integer.MAX_VALUE >> 4) powoduje, że ListView mierzy wszystkie swoje potomne do podanej (bardzo dużej) wysokości i odpowiednio ustawia wysokość.
Działa to lepiej niż inne rozwiązania z kilku powodów:
- Mierzy wszystko poprawnie (wypełnienie, przekładki)
- Mierzy ListView podczas przejścia miary
- Ze względu na # 2, poprawnie obsługuje zmiany szerokości lub liczby elementów bez dodatkowego kodu
Z drugiej strony, można argumentować, że robienie tego polega na nieudokumentowanym zachowaniu w zestawie SDK, które może ulec zmianie. Z drugiej strony można argumentować, że tak właśnie wrap_content powinien naprawdę współpracować z ListView i że bieżące zachowanie wrap_content jest po prostu zepsute.
Jeśli obawiasz się, że zachowanie może się zmienić w przyszłości, powinieneś po prostu skopiować funkcję onMeasure i powiązane funkcje z ListView.java do swojej własnej podklasy, a następnie wykonać ścieżkę AT_MOST przez uruchomienie onMeasure również dla NIEPECYFIKOWANEJ.
Nawiasem mówiąc, uważam, że jest to całkowicie poprawne podejście, gdy pracujesz z małą liczbą elementów listy. Może być nieefektywny w porównaniu do LinearLayout, ale gdy liczba elementów jest niewielka, użycie LinearLayout jest niepotrzebną optymalizacją, a zatem niepotrzebną złożonością.