it-roy-ru.com

Предельная высота ListView на Android

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

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

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

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

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


Правка: Я получил много полезных ответов.

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

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

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

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

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

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

86
jellyfish

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

РЕДАКТИРОВАТЬвот что я имею в виду:

<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>
51
AngeloS

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

61
shaylh

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

21
Adinia

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

6
ernazm

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

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

5
bigstones

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

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

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

2
user2994360

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

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

RelativeLayout

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

- RelativeLayout

---- кнопка

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

2
Rich

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

Похоже, они оба отлично работают по крайней мере на 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>

Activity предоставляет стандартный код для проверки решения самостоятельно. 

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);
            }
        });
    }
}

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

2
Richard Le Mesurier

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

1
Maxim

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

1
DawnYu

Вот что у меня сработало ...

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

0

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

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

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

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

<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"/>
0
Jenny Pushkarskaya