ListView на самом деле уже способен измерять себя, чтобы быть достаточно высоким для отображения всех элементов, но он не делает этого, когда вы просто указываете wrap_content (MeasureSpec.UNSPECIFIED). Он будет делать это, если задана высота с помощью MeasureSpec.AT_MOST. Обладая этими знаниями, вы можете создать очень простой подкласс для решения этой проблемы, который работает намного лучше, чем любое из решений, опубликованных выше. Вы все равно должны использовать wrap_content с этим подклассом.
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));
}
}
Манипулирование heightMeasureSpec как AT_MOST с очень большим размером (Integer.MAX_VALUE >> 4) приводит к тому, что ListView измеряет всех своих дочерних элементов до заданной (очень большой) высоты и соответственно устанавливает свою высоту.
Это работает лучше, чем другие решения, по нескольким причинам:
- Все правильно измеряет (отступы, разделители)
- Он измеряет ListView во время прохода измерения
- Из-за # 2 он правильно обрабатывает изменения ширины или количества элементов без какого-либо дополнительного кода.
С другой стороны, вы можете утверждать, что это зависит от недокументированного поведения в SDK, которое может измениться. С другой стороны, вы можете возразить, что именно так wrap_content действительно должен работать со ListView и что текущее поведение wrap_content просто нарушено.
Если вас беспокоит, что поведение может измениться в будущем, вам следует просто скопировать функцию onMeasure и связанные с ней функции из ListView.java в свой собственный подкласс, а затем сделать путь AT_MOST через onMeasure также для НЕПРЕДВИДЕННОГО.
Кстати, я считаю, что это совершенно правильный подход, когда вы работаете с небольшим количеством элементов списка. Это может быть неэффективно по сравнению с LinearLayout, но когда количество элементов невелико, использование LinearLayout является ненужной оптимизацией и, следовательно, ненужной сложностью.
person
Jason Y
schedule
17.04.2015
ListView
.ListView
может иметь несколько стилей строк, а также невыбираемые строки. - person CommonsWare   schedule 05.04.2013