Как получить GridView, который адаптирует свою высоту при добавлении элементов - PullRequest
27 голосов
/ 15 мая 2011

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

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

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

  • a View с LinearLayout, сам с CheckBox и EditText для первых n элементов,
  • LinearLayout с простой кнопкой, с '+ заголовок для 'n + 1' элемента.

Пока все хорошо.Когда нажата кнопка «+», я добавляю пустую строку в список строк и вызываю 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>

Флажок + строковый элемент из адаптера определяется следующим образом:

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

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

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

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

Ответы [ 6 ]

51 голосов
/ 12 июня 2014

Используйте этот код

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);
    }
}
8 голосов
/ 05 мая 2016

Я сделал так:

Этот код установит GridView высоту согласно числу из дочернему элементу .

Примечание: Где 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);
    }

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

4 голосов
/ 22 марта 2013

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

<?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>
4 голосов
/ 23 декабря 2011

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

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, MeasureSpec.UNSPECIFIED);
    }
1 голос
/ 07 января 2012

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

0 голосов
/ 20 ноября 2018

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

public class MyGridView extends GridView {
    public MyGridView(Context context) {
        super(context);
    }

    public MyGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyGridView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

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

        // set childs height to same value as child that has highest value
        for(int i=0; i<getChildCount(); i++) {
            MyLinearLayout child = (MyLinearLayout) getChildAt(i);
            AbsListView.LayoutParams params = (AbsListView.LayoutParams) child.getLayoutParams();
            params.height = MyLinearLayout.maxHeight;
            child.setLayoutParams(params);
        }

        // calculate total height and apply to the grid
        double numRow = Math.ceil((double) getCount() / (double) getNumColumns());
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) this.getLayoutParams();
        params.height = (int) numRow *  MyLinearLayout.maxHeight;
        this.setLayoutParams(params);

        // invalidate after change grid's height
        this.invalidate();
    }
}

MyLinearLayout class

public class MyLinearLayout extends LinearLayout {
    public static int maxHeight = 0;

    public MyLinearLayout(Context context) {
        super(context);
    }

    public MyLinearLayout(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MyLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (maxHeight<this.getMeasuredHeight()) maxHeight=this.getMeasuredHeight();
    }
}

GridView содержит некоторые дочерние элементы MyLinearLayout, и это макет

<?xml version="1.0" encoding="utf-8"?>
<com.mysystem.view.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="100dp"
              android:layout_height="100dp"
              android:background="#ddd"
              android:padding="0.5dp"
              android:layout_gravity="top"
              android:gravity="center_horizontal"
              android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#fff"
        android:padding="20dp"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/img_menu"
            android:layout_width="30dp"
            android:layout_gravity="center_horizontal"
            android:layout_height="30dp"
            android:layout_marginTop="5dp"/>

        <TextView
            android:id="@+id/tv_menu"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:textAlignment="center"
            android:textColor="#000"
            android:text="Title"
            android:textSize="10sp"/>

    </LinearLayout>
</com.mysystem.view.MyLinearLayout>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...