ListView sebenarnya sudah mampu mengukur dirinya cukup tinggi untuk menampilkan semua item, tetapi tidak melakukan ini ketika Anda cukup menentukan wrap_content (MeasureSpec.UNSPECIFIED). Ini akan melakukan ini ketika diberi ketinggian dengan MeasureSpec.AT_MOST. Dengan pengetahuan ini, Anda dapat membuat subclass yang sangat sederhana untuk menyelesaikan masalah ini yang bekerja jauh lebih baik daripada solusi yang diposting di atas. Anda harus tetap menggunakan wrap_content dengan subclass ini.
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));
}
}
Memanipulasi heightMeasureSpec menjadi AT_MOST dengan ukuran yang sangat besar (Integer.MAX_VALUE >> 4) menyebabkan ListView mengukur semua anak-anaknya hingga ketinggian (sangat besar) yang diberikan dan mengatur tingginya.
Ini berfungsi lebih baik daripada solusi lain karena beberapa alasan:
- Ini mengukur semuanya dengan benar (padding, pembagi)
- Ini mengukur ListView selama pass pengukuran
- Karena # 2, ia menangani perubahan lebar atau jumlah item dengan benar tanpa kode tambahan
Pada sisi negatifnya, Anda bisa berpendapat bahwa melakukan ini bergantung pada perilaku tidak berdokumen di SDK yang dapat berubah. Di sisi lain, Anda bisa berpendapat bahwa ini adalah bagaimana wrap_content harus benar-benar berfungsi dengan ListView dan bahwa perilaku wrap_content saat ini baru saja rusak.
Jika Anda khawatir bahwa perilaku tersebut dapat berubah di masa mendatang, Anda cukup menyalin fungsi onMeasure dan fungsi terkait dari ListView.java dan ke dalam subkelas Anda sendiri, lalu buat jalur AT_MOST melalui onMeasure yang dijalankan untuk UNSPECIFIED juga.
Omong-omong, saya percaya bahwa ini adalah pendekatan yang benar-benar valid ketika Anda bekerja dengan sejumlah kecil item daftar. Mungkin tidak efisien jika dibandingkan dengan LinearLayout, tetapi ketika jumlah item kecil, menggunakan LinearLayout adalah optimasi yang tidak perlu dan karenanya kompleksitas yang tidak perlu.