Match_parent не работает, как ожидалось

Я предполагаю, что это должно быть довольно легко ответить, если вы понимаете XML-макеты лучше, чем я. Кажется, я не понимаю, что я думал, когда должен использовать match_parent layout_height.

У меня есть корневой элемент LinearLayout с android: orientation = "vertical" . Внутри этого LinearLayout я хочу три элемента: – TextView – ListView – TextView

Для обоих TextViews я устанавливаю android: layout_height = "wrap_content", чтобы они были только высотой, необходимой для отображения их содержимого. Дело в том, что я хочу, чтобы один TextView сидел в верхней части формы, а другой – в нижней части формы, в то время как ListView заполняет все пространство, доступное в форме. Итак, вот как выглядит мой xml-макет:

<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="30sp" android:text="Top TextView" /> <ListView android:id="@+id/listView_Species" android:layout_width="match_parent" android:layout_height="match_parent" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="30sp" android:text="Bottom TextView" /> 

Но это не сработает. Вот что я получаю. Я выбрал ListView так, чтобы он был выделен. Обратите внимание, как он распространяется до самого конца формы, нажав нижний TextView на форму. XML-макет 1

Когда я изменяю свойство layout_height ListView на некоторое фиксированное значение, например 180dp, это выглядит так. Я просто размещаю это, чтобы доказать, что нижний TextView есть, но я до сих пор не знаю, как его фиксировать в нижней части экрана, в то время как ListView занимает все пространство, но между двумя TextViews.

XML-макет 2

Заранее спасибо.

Solutions Collecting From Web of "Match_parent не работает, как ожидалось"

В то время как другие ответы пытаются исправить вашу проблему (чего они не на самом деле – они предлагают вам делать что-то похожее, но могут или не могут выглядеть хорошо на разных устройствах), никто не заполнил пробелы в ваших знаниях LinearLayouts И match_parent. И эти пробелы очень распространены – документация Google по-прежнему намного ниже звездной.

Во-первых, как работают Views в LinearLayout? Предположим, что orientation="vertical" для простоты.

  1. Изучите высоту первого ребенка LinearLayout (LL для краткости). Если высота соответствует match_parent или fill_parent (старое имя для одной и той же вещи), тогда высота представления растягивается, чтобы заполнить всю область просмотра. Если высота – wrap_content , то измерьте вертикальное пространство, которое занимает View, и используйте это пространство для представления. Если высота является ненулевым числом, используйте точно столько пикселей для высоты представления (возможно, зажим, если он слишком мал). Если высота равна 0, см. Ниже.
  2. Поместите следующий вид под видом в 1. Проверьте его высоту и действуйте соответствующим образом.
  3. Продолжайте просмотр всех представлений. Если представление сдвинуто вниз, продолжайте и прекратите вычислять, потому что никто не увидит его или какие-либо последующие представления (если не считать ScrollView).
  4. Если высота представления равна 0, проверьте его gravity . Это требует второго прохода, сохраняя гравитацию всех видов, а затем пропорционально распределяя их высоты. Как вы можете догадаться, второй проход удваивает временную компоновку, что не существенно для простых макетов.

Объяснение вашего примера : первый ребенок LL (первый TextView) измеряется и занимает определенное количество пикселей. Затем ваш ListView занимает все оставшееся пространство (через match_parent ). И тогда ваш второй TextView не рисуется вообще, поскольку он находится в нижней части экрана. Это в значительной степени то, что вы наблюдали, но теперь вы понимаете, почему.

Решение . Используйте RelativeLayout . В этом случае отлично работает.

 <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/top_tv" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:textSize="30sp" android:text="Top TextView" /> <TextView android:id="@+id/bottom_tv" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:textSize="30sp" android:text="Bottom TextView" /> <ListView android:id="@+id/listView_Species" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/top_tv" android:layout_above="@id/bottom_tv" /> </RelativeLayout> 

RelativeLayout сообщает компоновщику макета, чтобы нарисовать первый TextView сверху, затем нарисовать второй TextView внизу, а затем заполнить остальную часть пространства ListView. Я считаю, что это именно то, что вы хотите.

Добро пожаловать на Android. Вы будете использовать этот шаблон LOT!

Измените высоту ListView на 0dp и добавьте weight=1
то есть:

 <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="30sp" android:text="Top TextView" /> <ListView android:id="@+id/listView_Species" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="30sp" android:text="Bottom TextView" /> 

Используйте android: layout_weight, чтобы определить весы для ваших виджетов внутри самого внешнего макета. Объявите их высоту как 0dp а затем определите android:layout_weight для каждого из них. Общая сумма взвешивания трех из них должна быть 1. В соответствии с вашей потребностью вы можете определить 0.1 вес как для верхнего, так и для нижнего TextView и определить 0.8 для ListView.

 <TextView android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight = "0.1" android:textSize="30sp" android:text="Top TextView" /> <ListView android:id="@+id/listView_Species" android:layout_width="match_parent" android:layout_weight = "0.8" android:layout_height="0dp" /> <TextView android:layout_width="match_parent" android:layout_height="0dp" android:textSize="30sp" android:layout_weight = "0.1" android:text="Bottom TextView" />