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

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

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

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

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

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


Изменить: Я получил много полезных ответов.

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

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

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

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

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

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

Ответ 1

У меня была эта точная проблема, и для ее решения я создал два отдельных LinearLayouts для размещения ListView и Button соответственно. Оттуда я разместил оба в другом Linear Layout и установил для этого контейнера android:orientation значение vertical. Я также установил вес LinearLayout, в котором размещался ListView до 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>

Ответ 2

Я решил эту проблему в коде, установив высоту listview только в том случае, если она содержит более 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 раза больше высоты одного элемента, поэтому пользователь точно знает, что есть прокрутка!:)

Ответ 3

В последнем редакторе вам просто нужно добавить 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>

и результат, используя случайный список:
enter image description here

Ответ 4

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

Ответ 5

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

Было бы одинаково, если бы вы использовали LinearLayout: способ достичь того, что вы хотите, - установить ListView на высоту = 0 и вес = 1, а для высоты кнопки = wrap_content и weight = 0. (установка как wrap_content, так и user639183, не ограничивает высоту ListView).

Ответ 6

Найден способ сделать это без использования вложенных контейнеров, вдохновленных решением 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"
    />

Ответ 7

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

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

RelativeLayout

- ListView

- RelativeLayout

---- Кнопка

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

Ответ 8

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

<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, чтобы обернуть кнопку.

Ответ 9

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

Оба они, кажется, работают отлично, по крайней мере, на v4.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);
            }
        });
    }
}

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

Ответ 10

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

Ответ 11

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

Ответ 12

Следующее - то, что сработало для меня...

 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...

Ответ 13

обернуть содержимое в линейном макете

в списке просмотра добавить: 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>

Ответ 14

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

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

<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"/>

Ответ 15

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

Ответ 16

Я решил это, поставив 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>