Подтвердить что ты не робот

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;

Спасибо!

4b9b3361

Ответ 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;
}