Как получить 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)

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

 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