Ограничение высоты ListView на Android

Я хочу показать кнопку в ListView . Проблема в том, что если ListView получает расширение (элементы добавлены …), кнопка выталкивается из экрана.

Я попробовал LinearLayout с весами (как было предложено в Android: почему нет maxHeight для просмотра? ), Но либо я ошибался, либо просто не работал.

Кроме того, я нашел где-то подсказку использовать RelativeLayout . Затем ListView будет установлен над кнопкой с параметром android:layout_above .

Проблема в том, что я не знаю, как позиционировать кнопку после этого. В примере, который я нашел, представление ниже ListView было настроено с помощью android:layout_alignParentBottom , но я не хочу, чтобы моя кнопка android:layout_alignParentBottom за нижнюю часть экрана.

Любые идеи, кроме использования метода setHeight и некоторого вычисления необходимого пространства?


Редактирование: у меня много полезных ответов.

  • Решение bigstone & user639183 почти отлично работало. Тем не менее, мне пришлось добавить дополнительный отступ / край в нижней части кнопки, так как он все равно будет вытолкнут наполовину из экрана (но затем остановится)

  • Ответ Адинии с относительным расположением только хорош, если вы хотите, чтобы кнопка была зафиксирована в нижней части экрана. Это не то, что я намеревался, но все же может быть полезным для других.

  • Решение AngeloS было тем, что я выбрал в конце, поскольку он только что создал эффекты, которые я хотел. Тем не менее, я сделал два незначительных изменения в LinearLayout вокруг кнопки:

    • Во-первых, поскольку я не хотел иметь никаких абсолютных значений в своем макете, я изменил android:layout_height="45px" на wrap_content , который также отлично работает.

    • Во-вторых, поскольку я хотел, чтобы кнопка была центрирована по горизонтали, которая поддерживается только вертикальным LinearLayout , я изменил андроид: ориентация = «горизонтальная» на «вертикальная».

    AngeloS также заявил в своем первоначальном сообщении, что он не был уверен, что какой-либо эффект имеет параметр android:layout_weight="0.1" в LinearLayout вокруг ListView ; Я просто попробовал, и это на самом деле! Без кнопки кнопка снова выталкивается из экрана.

Solutions Collecting From Web of "Ограничение высоты ListView на Android"

У меня была эта точная проблема, и для ее решения я создал два отдельных LinearLayouts для размещения ListView и Button соответственно. Оттуда я помещал оба в другой Linear Layout и устанавливал android:orientation для vertical . Я также установил вес LinearLayout который размещал ListView LinearLayout 0.1 но я не знаю, имеет ли это эффект. Оттуда вы можете установить высоту нижнего контейнера (с вашей кнопкой) на любую высоту, которая вам нужна.

EDIT это то, что я имею в виду:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="0.1" > <ListView android:id="@+id/ListView01" android:layout_height="fill_parent" android:layout_width="fill_parent" android:dividerHeight="2px"> </ListView> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="45px" android:background="@drawable/drawable" > <Button android:background="@drawable/btn_more2" android:id="@+id/moreButton" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_alignParentRight="true" android:paddingRight="20px" /> </LinearLayout> </LinearLayout> 

Вышеупомянутое решение зафиксирует кнопку в нижней части экрана.


Чтобы кнопка плавала в нижней части списка, измените высоту ListView01 на wrap_content :

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="0.1" > <ListView android:id="@+id/ListView01" android:layout_height="wrap_content" android:layout_width="fill_parent" android:dividerHeight="2px"> </ListView> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="45px" android:background="@drawable/drawable" > <Button android:background="@drawable/btn_more2" android:id="@+id/moreButton" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_alignParentRight="true" android:paddingRight="20px" /> </LinearLayout> </LinearLayout> 

Я решил эту проблему в коде, установив высоту списка, только если в ней содержится более 5 элементов:

 if(adapter.getCount() > 5){ View item = adapter.getView(0, null, listView); item.measure(0, 0); ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, (int) (5.5 * item.getMeasuredHeight())); listView.setLayoutParams(params); } 

Обратите внимание, что я устанавливаю максимальную высоту в 5,5 раза больше высоты одного элемента, поэтому пользователь точно знает, что есть прокрутка! 🙂

В последнем редакторе вам просто нужно добавить android:layout_above="@+id/butt1" в свой код ListView.

И чтобы показать вам (и всем здесь, кто раньше попытался ответить), что вам действительно не нужно использовать более одного RelativeLayout , вот ваш исправленный код :

  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/bkg"> <TextView android:id="@+id/textView1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="TextView1" android:layout_alignParentTop="true"> </TextView> <TextView android:id="@+id/textView2" android:layout_below="@+id/textView1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="TextView2" android:layout_centerHorizontal="true"> </TextView> <Button android:id="@+id/butt1" android:text="string/string3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_alignParentBottom="true"> </Button> <ListView android:id="@+id/android:list" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="2dip" android:layout_marginBottom="2dip" android:drawSelectorOnTop="false" android:visibility="visible" android:layout_below="@+id/textView2" android:layout_above="@+id/butt1" /> </RelativeLayout> 

И результат , используя некоторый случайный список:
Введите описание изображения здесь

Используя LinearLayout , установите высоту вашего ListView и Button в wrap_content и добавьте вес = 1 в ListView . Это должно работать так, как вы хотите.
И да, установите layout_gravity Button на bottom

RelativeLayout – это решение, если вы не хотите, чтобы кнопка оставалась слишком близко к основанию, вы можете добавлять поля (добавление кнопки может сломать ее, потому что она использует фон с 9 патчами и устанавливает собственное дополнение).

Это было бы так же, если вы использовали LinearLayout : способ достижения желаемого – установить ListView на высоту = 0 и вес = 1, а для кнопки height = wrap_content и weight = 0. (Установка как wrap_content, так и user639183, не ограничивает высоту ListView ).

Нашел способ сделать это без использования вложенных контейнеров, вдохновленных решением AngeloS.

Я использовал LinearLayout с вертикальной ориентацией, которая имеет ListView и кнопку. Я установил android:layout_weight="0.1" для ListView .

Ему удается всегда удерживать кнопку в нижней части списка. И кнопка не сбрасывается с экрана, когда список растет.

 <ListView android:id="@+id/notes_list" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="0.1" /> <Button android:id="@+id/create_note_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="onCreateButtonClicked" android:text="@string/create_notes" /> 

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

Возможно что-то вроде этого:

RelativeLayout

— Посмотреть список

– RelativeLayout

—- Кнопка

Используя различные параметры выравнивания на двух контейнерах, вы сможете заставить это работать.

Это самый чистый способ сделать это:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical"> <ListView android:id="@+id/ListView01" android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1" android:dividerHeight="2px"> </ListView> <FrameLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@drawable/drawable" > <Button android:background="@drawable/btn_more2" android:id="@+id/moreButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:paddingRight="20px" /> </LinearLayout> </LinearLayout> 

Он похож на решение Angelos, но вам не нужен linearlayout, который завершает ListView. Также вы можете использовать FrameLayout, который легче сравнить с LinearLayout, чтобы обернуть кнопку.

Идея изложена в очень хороших решениях:

  • Ангелос
  • искриться

Оба они, похоже, работают отлично, по крайней мере, на v.4.4.3.

Мне все же пришлось потратить некоторое время на создание тестового кода, чтобы проверить его и подтвердить каждый метод. Ниже приведен собственный код минимального кода.


Макет основан на решении Sparkle, поскольку он содержит меньше вложенных макетов. Также был обновлен, чтобы отразить текущие проверки LINT.

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" tools:context="MainActivity" > <ListView android:id="@+id/listview" android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1" /> <Button android:id="@+id/btn" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Grow List" tools:ignore="HardcodedText" /> </LinearLayout> 

Активность обеспечивает шаблонный код для проверки решения для себя.

 public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final ListView listview = (ListView)findViewById(R.id.listview); final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, new ArrayList<String>()); adapter.setNotifyOnChange(true); listview.setAdapter(adapter); findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int count = adapter.getCount(); adapter.add(String.valueOf(count)); listview.setSelection(count); } }); } } 

Не стесняйтесь добавлять или улучшать, так как это «вики сообщества».

Попробуйте использовать RelativeLayout с кнопкой внизу. Задайте высоту макета как «wrap_content». Я не пробовал. Просто идея

В LinearLayout, просто добавьте android:layout_weight="1" к вам ListView

Следующее – это то, что сработало для меня …

  if(adapter.getCount() > 3){ View item = adapter.getView(0, null, impDateListView); item.measure(0, 0); LayoutParams params = impDateListView.getLayoutParams(); params.width = LayoutParams.MATCH_PARENT; params.height = 3 * item.getMeasuredHeight(); impDateListView.setLayoutParams(params); } 

Примечание: params.width = … Нужно также установить …

Вышеприведенный пример – когда вы используете TableRow и ListView внутри TableRow …

Обертка содержимого в линейной компоновке

В виде списка добавить: android: layout_weight = "1"

В вашей кнопке установлена ​​фиксированная высота

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <ListView android:id="@+id/my_list" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1"> </ListView> <Button android:text="Button" android:layout_width="match_parent" android:layout_height="50dp"/> </LinearLayout> 

Если вы хотите, чтобы содержимое, расположенное ниже списка, перемещалось вниз по мере добавления элементов в список, попробуйте это решение:

Добавьте положительное дополнение к нижней части списка и отрицательное дополнение к верхней части «нижнего колонтитула». Это будет работать в линейной компоновке или относительной компоновке.

 <ListView android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingBottom="50dp"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="-50dp"/> 

Поскольку атрибута MaxHeight нет, лучше всего либо установить высоту ListView на заданное значение, либо использовать wrap_content .

Я решил это, поставив ListView внутри ScrollView. Линт не понравился, но, добавив minHeight и установив fillViewport в true, у меня хороший результат.

  <ScrollView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="1dp" android:layout_marginRight="1dp" android:minHeight="100dp" android:fillViewport="true" android:fadeScrollbars="false" android:paddingTop="2dp" android:orientation="vertical" android:scrollbarAlwaysDrawVerticalTrack="true" > <ListView android:id="@+id/workoutAElistRoutines" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="fill_vertical" android:background="@drawable/dialog_inner_border_tan" android:choiceMode="singleChoice" android:orientation="vertical" android:paddingLeft="3dp" android:paddingRight="3dp" > </ListView> </ScrollView> 1  <ScrollView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="1dp" android:layout_marginRight="1dp" android:minHeight="100dp" android:fillViewport="true" android:fadeScrollbars="false" android:paddingTop="2dp" android:orientation="vertical" android:scrollbarAlwaysDrawVerticalTrack="true" > <ListView android:id="@+id/workoutAElistRoutines" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="fill_vertical" android:background="@drawable/dialog_inner_border_tan" android:choiceMode="singleChoice" android:orientation="vertical" android:paddingLeft="3dp" android:paddingRight="3dp" > </ListView> </ScrollView> 1  <ScrollView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="1dp" android:layout_marginRight="1dp" android:minHeight="100dp" android:fillViewport="true" android:fadeScrollbars="false" android:paddingTop="2dp" android:orientation="vertical" android:scrollbarAlwaysDrawVerticalTrack="true" > <ListView android:id="@+id/workoutAElistRoutines" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="fill_vertical" android:background="@drawable/dialog_inner_border_tan" android:choiceMode="singleChoice" android:orientation="vertical" android:paddingLeft="3dp" android:paddingRight="3dp" > </ListView> </ScrollView>