У меня есть три виджета ListView
в том же LinearLayout
. Что-то вроде этого (я пропускаю XML-элементы, которые не актуальны в этом примере):
<LinearLayout> <ListView android:layout_width="fill_parent" android:layout_height="360dp"/> <ListView android:layout_width="fill_parent" android:layout_height="360dp"/> <ListView android:layout_width="fill_parent" android:layout_height="360dp"/> </LinearLayout>
Это заставляет список иметь высоту 360 градусов. Конечно, это будет его высота, даже если есть несколько элементов списка. Итак, мой вопрос заключается в том, как заставить списки иметь автоматическую высоту? Я хочу, чтобы высота ListView
точного размера суммы всех элементов списка.
Я реализовал его таким образом (код работает, поэтому это скорее источник идеи, чем решение):
package com.customcontrols; public class NoScrollListView extends ListView { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0) ); // here I assume that height's being calculated for one-child only, seen it in ListView's source which is actually a bad idea int childHeight = getMeasuredHeight() - (getListPaddingTop() + getListPaddingBottom() + getVerticalFadingEdgeLength() * 2); int fullHeight = getListPaddingTop() + getListPaddingBottom() + childHeight*(getCount()); setMeasuredDimension(getMeasuredWidth(), fullHeight); } }
Расчет не идеальный, но он близок и работает до сих пор. После этого вы просто создаете такой макет:
ScrollView com.customcontrol.NoScrollListView com.customcontrol.NoScrollListView com.customcontrol.NoScrollListView / ScrollView
ScrollView имеет решающее значение, так как вы можете легко исчерпать границы экрана.
PS. Прямая операционная система вычислений, поскольку большинство методов расчета в ListView & Co являются закрытыми пакетами, что довольно странный выбор для общедоступных классов для пользовательского интерфейса.
Вместо редактирования моего предыдущего ответа, вот моя фактическая версия (после того, как, наконец, дело стало проблемой, и я должен был ее исправить)
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0)); int childHeight = getMeasuredHeight() - (getListPaddingTop() + getListPaddingBottom() + getVerticalFadingEdgeLength() * 2); // on a first run let's have a space for at least one child so it'll trigger remeasurement int fullHeight = getListPaddingTop() + getListPaddingBottom() + childHeight*(getCount()); int newChildHeight = 0; for (int x = 0; x<getChildCount(); x++ ){ View childAt = getChildAt(x); if (childAt != null) { int height = childAt.getHeight(); newChildHeight += height; } } //on a second run with actual items - use proper size if (newChildHeight != 0) fullHeight = getListPaddingTop() + getListPaddingBottom() + newChildHeight; setMeasuredDimension(getMeasuredWidth(), fullHeight); }
Самая сложная часть состоит в том, что onMeasure получает вызов дважды, сначала для приблизительной компоновки, а затем после того, как элементы добавлены для точного, и оба должны возвращать разумные результаты.
Я нашел решение по набору ListView Height Based On Children , эта работа
public static void setListViewHeightBasedOnChildren(ListView listView) { ListAdapter listAdapter = listView.getAdapter(); if (listAdapter == null) { // pre-condition return; } int totalHeight = 0; for (int i = 0; i < listAdapter.getCount(); i++) { View listItem = listAdapter.getView(i, null, listView); listItem.measure(0, 0); totalHeight += listItem.getMeasuredHeight(); } ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); listView.setLayoutParams(params); listView.requestLayout(); }
Вы можете попробовать выполнить итерацию по строкам ListView
(см. Методы в ViewGroup
), найти их высоты, суммировать их и изменить высоту ListView
.
Сказав это, я полностью ожидаю, что это будет ужасно:
Если ваша цель состоит в том, чтобы иметь единственный список, но у вас есть три источника данных, объедините данные и поместите их в один список. Мой MergeAdapter
может помочь здесь.
Попробуйте это … list view real height
Просмотр списка в формате xml
<ListView android:id="@+id/my_listview" android:layout_width="match_parent" android:layout_height="match_parent" />
Просмотр списка java-кодирования
ListView lView = (ListView)findViewById(R.id.my_listview); lView.setAdapter(adapter); setListViewHeightBasedOnChildren(lView);
Метод setListViewHeightBasedOnChildren
public static void setListViewHeightBasedOnChildren(ListView listView) { ListAdapter listAdapter = listView.getAdapter(); if (listAdapter == null) { return; } int totalHeight = 0; for (int i = 0; i < listAdapter.getCount(); i++) { View listItem = listAdapter.getView(i, null, listView); listItem.measure(0, 0); totalHeight += listItem.getMeasuredHeight(); } ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); listView.setLayoutParams(params); listView.requestLayout(); }