ListView in realtà è già in grado di misurarsi per essere abbastanza alto da visualizzare tutti gli elementi, ma non lo fa quando si specifica semplicemente wrap_content (MeasureSpec.UNSPECIFIED). Lo farà quando viene data un'altezza con MeasureSpec.AT_MOST. Con questa conoscenza, è possibile creare una sottoclasse molto semplice per risolvere questo problema che funziona molto meglio di una qualsiasi delle soluzioni sopra pubblicate. Dovresti comunque usare wrap_content con questa sottoclasse.
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));
}
}
Manipolando heightMeasureSpec su AT_MOST con una dimensione molto grande (Integer.MAX_VALUE >> 4), ListView misura tutti i suoi figli fino all'altezza (molto grande) e imposta la sua altezza di conseguenza.
Funziona meglio delle altre soluzioni per alcuni motivi:
- Misura tutto correttamente (imbottitura, divisori)
- Misura il ListView durante il passaggio di misura
- A causa di # 2, gestisce correttamente le modifiche in larghezza o numero di elementi senza alcun codice aggiuntivo
Il rovescio della medaglia, si potrebbe sostenere che farlo dipende dal comportamento non documentato nell'SDK che potrebbe cambiare. D'altra parte, si potrebbe sostenere che questo è il modo in cui wrap_content dovrebbe davvero funzionare con ListView e che l'attuale comportamento di wrap_content è appena rotto.
Se sei preoccupato che il comportamento possa cambiare in futuro, devi semplicemente copiare la funzione onMeasure e le funzioni correlate da ListView.java e nella tua sottoclasse, quindi eseguire il percorso AT_MOST attraverso onMeasure anche per NON.
A proposito, credo che questo sia un approccio perfettamente valido quando si lavora con un numero limitato di voci di elenco. Può essere inefficiente rispetto a LinearLayout, ma quando il numero di elementi è ridotto, l'utilizzo di LinearLayout è un'ottimizzazione non necessaria e quindi una complessità non necessaria.