Почему элементы ListView не растут, чтобы обернуть их содержимое? - PullRequest
56 голосов
/ 02 ноября 2009

У меня довольно сложный ListView с переменной высотой элемента списка. При определенных условиях мне нужно отобразить дополнительный вид в элементе списка, который по умолчанию скрыт (View.GONE). Включив его (View.VISIBLE), элемент списка увеличивается в высоту (или, по крайней мере, так должно быть).

Проблема: Даже несмотря на то, что я объявляю корневой макет элемента как wrap_content, а каждый компонент в элементе - fill_parent, скрываемое / показываемое представление, которое должно изменять высоту элемента, просто обрезается внизу вместо его родителя (макет элемента) растет в высоту, чтобы полностью отобразить его.

Есть ли какие-либо ошибки, связанные с ListViews, макетами элементов и высотой элементов, которые я, возможно, пропустил?

Еще несколько замечаний:

В целях тестирования я теперь сократил макет элемента списка, чтобы он содержал только корневой LinearLayout и ImageView. Когда я устанавливаю высоту LinearLayout, например, 200dip и ImageView для fill_parent, я бы ожидал, что ImageView будет расти, пока не достигнет предела 200dip, установленного его родителем.

Однако вместо этого изображение будет всегда таким же высоким, как и его растровый ресурс (как если бы я установил его в wrap_content), и весь элемент списка будет иметь такую ​​же высоту (т.е. как если бы я установил его в wrap_content, тоже).

Если, однако, я установил высоту изображения, например, 200dip, то элемент списка будет расти в высоту, как и расположение элемента.

Другими словами, layout_height макета элемента списка полностью игнорируется, как и любое значение высоты в ImageView, кроме жестко заданного значения пикселя.

Ответы [ 8 ]

55 голосов
/ 04 ноября 2009

Мне удалось это исправить, но я не понимаю почему .

Как я уже говорил, я установил layout_height макета элемента списка на wrap_content (поскольку fill_parent здесь не имеет смысла, учитывая, что ListView бесконечно высок).

Однако я установил layout_height всех видов внутри этого макета на fill_parent. Проблема исчезла при установке их на wrap_content.

Это поднимает два других вопроса:

1) Какова семантика представления, запрашивающего fill_parent, когда родительский wraps_content? Какой размер запроса имеет приоритет?

2) Как мне заставить представление заполнить элемент списка, если fill_parent явно не работает?

Спасибо за ваш вклад, ребята.

28 голосов
/ 07 декабря 2011

Попробуйте это: http://www.java2s.com/Code/Android/UI/setListViewHeightBasedOnChildren.htm

public class Utils {

    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();
    }     
}
21 голосов
/ 02 ноября 2009

Как ты раздуваешь свои строки?

Если вы не используете его прямо сейчас, попробуйте использовать LayoutInflater#inflate(layoutId, parent, false) (где parent - это AdapterView, предоставленный getView() или newView()):

v = getLayoutInflater().inflate(R.layout.list_item, parent, false);
14 голосов
/ 20 февраля 2011

Проблемы с макетом могут быть вызваны тем, что ScrollView является оболочкой

Я наткнулся на какую-то записку в http://developer.android.com/reference/android/widget/ExpandableListView.html

"... Примечание: Вы не можете использовать значение wrap_content для атрибута android: layout_height ExpandableListView в XML, если размер родителя также не указан строго (например, если родителем был ScrollView, вы не могли бы указать wrap_content, поскольку он также может быть любой длины. Однако вы можете использовать wrap_content, если родительский элемент ExpandableListView имеет определенный размер, например 100 пикселей. "

Я удалил упаковку ScrollView, и линейный макет начал работать правильно. Теперь понятно только, как обернуть материал в ScrollView. Боже, помоги мне

Но в любом случае это действительно странное поведение. Я думаю, что fill_parent не совсем правильная формулировка. При использовании инструмента heirarchyviewer я всегда вижу значения WRAP_CONTENT и MATCH_PARENT для layout_width и leayout_height. Так что, вероятно, fill_parent на самом деле означает match_parent, который ставит меня в когнитивный диссонанс.

1 голос
/ 14 сентября 2012

Если вы используете пользовательский View в качестве элемента списка, который изменяет размер, то вы можете взять ответ PeBek и сделать это при создании View

addOnLayoutChangeListener(
            new OnLayoutChangeListener() {
                @Override
                public void onLayoutChange(View _, int __, int ___, int ____, int bottom, int _____, int ______,
                                           int _______, int old_bottom) {
                    final ListView list_view = (ListView) getParent();
                    final ViewGroup.LayoutParams params = list_view.getLayoutParams();
                    params.height += bottom - old_bottom;
                    list_view.setLayoutParams(params);
                    list_view.requestLayout();
                }
            });

Когда размер View будет изменен, этот метод обратного вызова будет запущен и обновит высоту ListView, чтобы включить изменение высоты (дельта-дно). Другие значения, если они окажутся полезными для вас: view (ссылка на представление), left, top, right, bottom, old_left, old_top, old_right, old_bottom. Он работает для расширения и свертывания вида.

API 11 требуется для OnLayoutChangeListener, не знаю, есть ли обратно совместимый способ сделать это.

1 голос
/ 22 июля 2010

Я использую «AbsListView.LayoutParams» для настройки ширины и высоты вручную внутри «Adapter.getView ()».

0 голосов
/ 16 ноября 2017

это работает для меня

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    android:padding="@dimen/activity_vertical_margin">

    <TextView
        android:id="@+id/tv_status"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:textSize="17sp"
        android:text="@string/text_list_devices" />

    <ListView
        android:id="@+id/lv_paired"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/activity_vertical_margin"
        android:cacheColorHint="#00000000"
        android:layout_above="@+id/signup_t"
        android:layout_below="@id/tv_status"
        />

    <Button

        android:id="@+id/signup_t"
        style="?android:textAppearanceSmall"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:textColor="@android:color/white"
        android:layout_alignParentBottom="true"
        android:text="Print All Records"
        android:typeface="sans"
        android:layout_marginLeft="45dp"
        android:layout_marginRight="45dp"
        android:textSize="24sp"
        android:background="@drawable/selector_for_button"
        android:textStyle="bold" />
</RelativeLayout>
0 голосов
/ 15 октября 2014

У меня была та же проблема: я хотел бы, чтобы внутри моей деятельности был список, заполняющий весь экран, либо когда устройство находится в вертикальном положении, чем в горизонтальном. Я решаю проблему, используя все Linear Layout с высотой, равной fill_parent, и устанавливаю высоту элемента в списке на 0dp, а layout_weight устанавливается на 1.

android:layout_weight="1"
android:layout_height="0dp"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...