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;

Спасибо!


person Maksym Gontar    schedule 29.07.2010    source источник
comment
есть что-то в вашем ряду? потому что listPreferredItemHeight является ссылкой на ресурс Android, который сам по себе не является значением, я думаю: developer.android.com/reference/android/   -  person Sephy    schedule 29.07.2010
comment
в начале список пуст   -  person Maksym Gontar    schedule 03.08.2010
comment
В подавляющем большинстве случаев вам просто нужна фиксированная известная высота. Просто установите minHeight в xml в макете ячейки. Вот и все.   -  person Fattie    schedule 28.12.2016


Ответы (4)


В Android представлению присваиваются ширина и высота только после завершения его рендеринга. Поэтому, если ваш список не будет отображаться хотя бы один раз, вы не получите listItemHeight. Решение вашей проблемы может состоять в том, что вы установите минимальную высоту элемента списка, чтобы у вас было хотя бы что-то для работы вместо высоты и ширины жесткого кодирования.

person Amit Chintawar    schedule 29.07.2010
comment
Также этот ответ SO, кажется, указывает в направлении android:minHeight. - person superjos; 18.11.2011
comment
Эй, братан.. часы попыток установить высоту списка не работают для меня в хорошем смысле. но установка minHeight дала мне луч надежды. - person Rushi Ayyappa; 20.08.2017

Попробуйте это, это сработает для вас.

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;
}
person Dwivedi Ji    schedule 20.09.2012
comment
Спасибо за код, это работает для получения размера еще не обработанной строки, но вопрос задавался о высоте строки, которая еще не вставлена ​​в ListView. - person hariseldon78; 26.03.2013
comment
Строки формируются в методах getView адаптера представления списка, поэтому вы можете просто найти высоту строки в getView. - person Dwivedi Ji; 01.04.2013
comment
@AshishDwivedi Я столкнулся с похожей проблемой, не могли бы вы предложить? - person Kanth; 30.05.2013
comment
Это не сработает, если у вас, например, есть длинное текстовое представление, которое переносится на несколько строк внутри дочернего представления. Необходимо указать ширину. - person Sver; 20.08.2013
comment
@Appu, не могли бы вы описать свою проблему. . - person Dwivedi Ji; 11.09.2013
comment
@DwivediJi Это нормально. Я решил это самостоятельно в тот же день. Спасибо за ответ спустя много дней. - person Kanth; 12.09.2013
comment
@Appu, я не являюсь постоянным пользователем Stackoverflow. так за .. извини братан - person Dwivedi Ji; 12.09.2013
comment
к комментарию @Sver: makeMeasureSpec(listView.getWidth(), android.view.View.MeasureSpec.AT_MOST)) должен помочь в качестве первого аргумента для измерения. - person TWiStErRob; 06.10.2013
comment
@DwivediJi Зачем вам передавать элементы в качестве аргумента? Есть ли проблема, если я использую mAdapter.getCount() вместо элементов? - person Ricardo; 26.01.2015
comment
@Ricardo Вы можете использовать метод mAdapter.getCount(). любезно измененный код в соответствии с вашим кодом. - person Dwivedi Ji; 23.04.2015
comment
Метод измерения дает мне исключение NullPointerException. Я думал, что он может получить высоту необработанных элементов. - person Alpaslan; 29.06.2015

оптимизированная версия кода 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;
}
person ashakirov    schedule 07.10.2014
comment
Я думаю, что количество делителей должно быть list.getCount() - 1 - person osrl; 14.02.2015
comment
И это дает всем элементам высоту. поэтому параметр items необходим, поскольку он сообщает, сколько элементов вы хотите добавить к общей высоте. - person osrl; 14.02.2015

Как указывает hariseldon78 выше, ни одно из этих решений не устраняет НАСТОЯЩУЮ проблему, которая определяет высоту строки элемента списка ДО ее отображения. У меня была та же проблема, так как я хотел масштабировать некоторые изображения до высоты строк элементов ListView и не хотел масштабировать их до фиксированного значения. Если тема вызывала изменение высоты текста в других частях моего макета строки, я хотел, чтобы высота была такой, чтобы в моей процедуре getView моего адаптера я мог соответствующим образом изменить размер bmap. Я боролся с проблемой, что getHeight и все измеренные высоты сообщают об нуле, пока строка не будет отображена. Для меня, увидев правильные высоты позже, было слишком поздно.

Мое решение состоит в том, чтобы создать onLayoutChangedListener() в первый раз через getView и только для строки 0. Слушатель сработает, как только getView для первой позиции (0) завершит выполнение, и в это время параметр «нижний» сообщит вам высота ряда. Я записываю это в пользовательскую переменную класса адаптера, чтобы она была доступна в качестве параметра высоты без необходимости повторного получения высоты.

Слушатель отменяет регистрацию как часть своего выполнения. Это обеспечивает правильную высоту для строк 1-N, но не для нулевой строки. Для нулевой строки я сделал что-то действительно неприятное. Мой слушатель снова вызвал getView для строки 0 после установки другой пользовательской переменной класса адаптера для управления рекурсией. Во второй раз, когда getView(0) запускается, он не будет настраивать прослушиватель и найдет допустимый параметр для высоты, с которым можно работать, и все в порядке.

Код ниже - не нужно говорить мне, насколько это УЖАСНО - если бы Android не пришлось так чертовски усложнять, чтобы определить, насколько большим является представление, которое я создаю, когда я закончу заполнение представления на основе параметров рендеринга для поверхность Мне не пришлось бы делать это безобразие, но это работает. Извините, если форматирование кода ужасно...

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;
}
person Mike Kogan    schedule 05.01.2014
comment
Вы можете использовать следующий макет, чтобы получить что-то вроде того, что вы хотели в первом абзаце в псевдо-android-xml: <LinearLayout orientation="horizontal" width="fill" height="wrap"><ImageView width="wrap" height="fill" scaleType="fitCenter" adjustViewBounds /><TextView width="0dp" weight="1.0" height="wrap" /> - person TWiStErRob; 07.06.2015
comment
@MikeKogan Спасибо, у меня это тоже сработало. У меня была проблема с экранами в корзине одного размера, но с разным разрешением. Пока не будет лучшего способа решить эту проблему, это похоже на путь. - person Adam Mendoza; 17.07.2016