Android - получить высоту элемента списка ListView?
Есть ли способ получить высоту ListViewItem в коде, если в списке нет фактических элементов?
Мой макет списка ListViewItem:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight">
...
</LinearLayout>
Я попытался получить его с помощью Inflater:
View convertView = LayoutInflater.from( this )
.inflate( R.layout.mail_list_row, null );
int itemHeight = convertView.getHeight();
Но он возвращает 0;
Спасибо!
Ответы
Ответ 1
В андроиде для представления присваивается ширина и высота только после завершения рендеринга. Поэтому, если вы не перечислите его, вы получите хотя бы один раз, когда вы не получите listItemHeight. Решение вашей проблемы может заключаться в том, что вы устанавливаете некоторую минимальную высоту элемента списка, чтобы у вас было по крайней мере что-то, с чем можно было работать, вместо высоты и ширины жесткого кодирования.
Ответ 2
Попробуй, это сработает для тебя.
private static final int UNBOUNDED = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
// To calculate the total height of all items in ListView call with items = adapter.getCount()
public static int getItemHeightofListView(ListView listView, int items) {
ListAdapter adapter = listView.getAdapter();
int grossElementHeight = 0;
for (int i = 0; i < items; i++) {
View childView = adapter.getView(i, null, listView);
childView.measure(UNBOUNDED, UNBOUNDED);
grossElementHeight += childView.getMeasuredHeight();
}
return grossElementHeight;
}
Ответ 3
оптимизированная версия кода Dwivedi Ji
с высотой разделителей и без лишних параметров:
private int calculateHeight(ListView list) {
int height = 0;
for (int i = 0; i < list.getCount(); i++) {
View childView = list.getAdapter().getView(i, null, list);
childView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
height+= childView.getMeasuredHeight();
}
//dividers height
height += list.getDividerHeight() * list.getCount();
return height;
}
Ответ 4
Как указано выше в Hariseldon78, ни одно из этих решений не устраняет проблему REAL, которая определяет высоту строки списка элементов перед ее визуализацией. У меня была та же проблема, что и для масштабирования некоторых изображений на высоте строк элемента списка ListView и не хотелось масштабировать их до фиксированного значения. Если тема привела к тому, что текст в других частях моей строки был разным по высоте, мне нужна высота, чтобы в моей процедуре getView моего адаптера я мог соответствующим образом изменить размер bmap. Я боролся с проблемой, что getHeight и все измеренные высоты сообщают ноль, пока строка не будет показана. Когда я увижу, что высоты верны позже, было слишком поздно.
Мое решение состоит в том, чтобы создать onLayoutChangedListener() в первый раз через getView и только для строки 0. Слушатель запускается, как только getView для первой позиции (0) завершает выполнение, и в то время параметр "bottom" скажет вам высоту строки. Я записываю это в переменную класса пользовательского адаптера, поэтому он доступен в качестве параметра высоты без необходимости снова получать высоту.
Слушатель отбрасывает себя как часть его выполнения. Это обеспечивает правильную высоту для строк 1-N, но не для нулевой строки. Для нулевой строки я сделал что-то действительно противное. У меня был прослушиватель вызова getView AGAIN для строки 0 после установки другой переменной класса адаптера для управления рекурсией. Во второй раз, когда getView (0) запускает, он не будет настраивать прослушиватель, и найдет допустимый параметр для высоты, чтобы работать, и все это хорошо.
Код ниже - не нужно рассказывать мне, как это AWFUL это - если андроид не должен был так сильно волноваться, чтобы сказать, насколько велика я создаю представление, когда я заполняю представление, основанное на рендеринге парм для поверхности мне не пришлось бы делать это уродство, но оно работает. Извините, если форматирование кода ужасно...
int mHeight = 0;
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
... usual boiler plate stuff
// JUST THE FIRST TIME
if (position == 0 && mHeight == 0) {
final View ref = convertView;
convertView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
public void onLayoutChange(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
ref.removeOnLayoutChangeListener(this);
mHeight = bottom;
firstTime = false;
// NOW LETS REGET THE FIRST VIEW WITH THE HEIGHT CORRECT
int visiblePosition = getListView().getFirstVisiblePosition();
View view = getListView().getChildAt(0 - visiblePosition);
getListAdapter().getView(0, view, getListView());
// RECURSION LOL
}
});
}
// Configure the view for this row
....
// HOW BIG IS THE VIEW?
// NOW IF NOT FIRSTTIME (MHEIGHT != 0)
if (mHeight != 0) {
// DO OUR IMAGE SETUP HERE CAUSE mHeight is RIGHT!
Log.d(TAG, "mHeight=" + mHeight);
}
return convertView;
}