Как получить GridView, который адаптирует его высоту при добавлении элементов

Я пытаюсь отобразить динамически растущий список строк с флажком в GridView, который сам является в TableLayout.

Я могу отобразить эти «checkboxed» строки в порядке. Моя проблема возникает, когда я позволяю пользователю динамически добавлять новые строки в GridView.

Я создал пользовательский адаптер, который получает список строк. Скажем, у нас есть n строк. Адаптер возвращает «n + 1» для подсчета элементов; В getView он возвращает:

  • A View с LinearLayout, сам имеющий CheckBox и EditText для первых n элементов,
  • LinearLayout с простой кнопкой, с надписью «+» для «n + 1'th item».

Все идет нормально. Когда нажимается кнопка «+», я добавляю пустую строку в список строк и вызываю notifyDataSetChanged в адаптере.

GridView перерисовывает себя еще одним элементом. НО он сохраняет свою первоначальную высоту и создает вертикальную полосу прокрутки. Я бы хотел, чтобы GridView увеличивал свою высоту (т. Е. Занимал больше места на экране и показывал все предметы).

Я попытался изменить экран на вертикальный LinearLayout вместо TableLayout, но результаты остались прежними.

Вот макет моего экрана:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:scrollbars="none"> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" > <!-- other lines omitted --> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/wine_rack_explanation" android:layout_gravity="center_vertical" /> <GridView android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/gvRack" android:columnWidth="90dp" android:numColumns="auto_fit" /> </LinearLayout> <!-- other lines omitted --> </LinearLayout> </ScrollView> 

Элемент checkbox + string из адаптера определяется следующим образом:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/cbCoordinate" android:checked="true" /> <EditText android:id="@+id/txtCoordinate" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> 

Элемент кнопки «+» определяется следующим образом:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"> <Button android:id="@+id/btnAddBottle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/add_bottle_caption" /> </LinearLayout> 

Я попытался вызвать invalidate или invalideViews в GridView после добавления элемента. Также называется invalidate на TableLayout и TableRow (в предыдущем макете экрана). Нет успеха.

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

(Обратите внимание, что я полностью открыт для использования другой группы представлений, чем GridView)

Solutions Collecting From Web of "Как получить GridView, который адаптирует его высоту при добавлении элементов"

Использовать этот код

 public class MyGridView extends GridView { public MyGridView(Context context, AttributeSet attrs) { super(context, attrs); } public MyGridView(Context context) { super(context); } public MyGridView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } } 

Я сделал так:

Этот код установит высоту GridView по числу Child .

Примечание: где 5 – количество столбцов.

 private void setDynamicHeight(GridView gridView) { ListAdapter gridViewAdapter = gridView.getAdapter(); if (gridViewAdapter == null) { // pre-condition return; } int totalHeight = 0; int items = gridViewAdapter.getCount(); int rows = 0; View listItem = gridViewAdapter.getView(0, null, gridView); listItem.measure(0, 0); totalHeight = listItem.getMeasuredHeight(); float x = 1; if( items > 5 ){ x = items/5; rows = (int) (x + 1); totalHeight *= rows; } ViewGroup.LayoutParams params = gridView.getLayoutParams(); params.height = totalHeight; gridView.setLayoutParams(params); } 

Надеюсь, что это поможет вам.

Это работает для меня:

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/root" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/background" > <!-- MORE LAYOUTS IF YOU WANT --> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:fillViewport="true" > <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <!-- MORE LAYOUTS IF YOU WANT --> <GridView android:id="@+id/gridview" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginBottom="10dp" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:layout_marginTop="5dp" android:gravity="center" android:horizontalSpacing="10dp" android:numColumns="auto_fit" android:stretchMode="columnWidth" android:verticalSpacing="10dp" > </GridView> <!-- MORE LAYOUTS IF YOU WANT --> </RelativeLayout> </ScrollView> </RelativeLayout> 

Когда onMeasure () вызывается для GridView, если heightMode является MeasureSpec.UNSPECIFIED, то gridview будет таким же высоким, как и все содержащиеся в нем элементы (плюс некоторые дополнения).

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

  @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, MeasureSpec.UNSPECIFIED); } 

Решение Грэма не сработало для меня. Однако этот (с немного большим взломом) сделал: https://stackoverflow.com/a/8483078/479478