it-swarm.com.de

So erstellen Sie eine GridView, die ihre Höhe beim Hinzufügen von Elementen anpasst

Ich versuche, eine dynamisch wachsende Liste von Zeichenfolgen mit einem Kontrollkästchen in einer GridView anzuzeigen, die sich selbst in einem TableLayout befindet.

Ich kann diese "markierten" Zeichenfolgen in einer Zeile anzeigen. Mein Problem tritt auf, wenn der Benutzer neue Zeichenfolgen in der GridView dynamisch hinzufügen kann.

Ich habe einen benutzerdefinierten Adapter erstellt, der die Liste der Zeichenfolgen empfängt. Angenommen, wir haben n Strings. Der Adapter gibt 'n + 1' für die Anzahl der Elemente zurück. In getView wird Folgendes zurückgegeben:

  • eine Ansicht mit einem LinearLayout, die selbst eine CheckBox und einen EditText für die ersten n Elemente enthält,
  • ein LinearLayout mit einer einfachen Schaltfläche und einem '+' - Titel für den 'n + 1'-Eintrag.

So weit, ist es gut. Wenn Sie auf die Schaltfläche "+" klicken, füge ich der Liste der Zeichenfolgen eine leere Zeichenfolge hinzu und rufe notifyDataSetChanged im Adapter auf. 

Die GridView zeichnet sich mit einem weiteren Element neu. ABER er behält seine ursprüngliche Höhe bei und erstellt eine vertikale Bildlaufleiste. Ich möchte, dass GridView seine Höhe vergrößert (d. H. Mehr Platz auf dem Bildschirm benötigt und alle Elemente anzeigt).

Ich habe versucht, den Bildschirm in ein vertikales LinearLayout anstelle eines TableLayout zu ändern, aber die Ergebnisse sind die gleichen.

Hier ist das Layout meines Bildschirms:

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

Das Kontrollkästchen + Zeichenfolgenelement aus dem Adapter wird folgendermaßen definiert:

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

Die Schaltfläche "+" ist folgendermaßen definiert:

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

Ich habe versucht, invalidate oder invalideViews in der GridView aufzurufen, nachdem ein Element hinzugefügt wurde. Wird im TableLayout und TableRow (im vorherigen Layout des Bildschirms) auch als ungültig bezeichnet. Kein Erfolg.

Gibt es eine Idee, warum das GridView seine Höhe nicht vergrößern möchte?

(Beachten Sie, dass ich völlig offen für die Verwendung einer anderen Ansichtsgruppe als der GridView bin.)

27
Timores

Verwenden Sie diesen Code

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

Ich habe diesen Weg gemacht:

Dieser Code setzt GridView height nach number von Child .

Hinweis: Dabei ist 5 die Anzahl der Spalten.

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

Hoffe, das wird dir helfen.

8
Hiren Patel

Wenn onMeasure () für GridView aufgerufen wird, und heightMode auf MeasureSpec.UNSPECIFIED gesetzt ist, ist das GridView so groß wie alle darin enthaltenen Elemente (und zusätzlich ein Füllzeichen).

Um sicherzustellen, dass dies der Fall ist, können Sie eine schnelle benutzerdefinierte Ansicht erstellen, die GridView erweitert und die folgende Überschreibung enthält: 

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

Das funktioniert für mich:

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

Grahams Lösung hat für mich nicht funktioniert. Allerdings hat dieser (mit etwas mehr Hacking): https://stackoverflow.com/a/8483078/479478

1
Eric Chen

Das funktioniert für mich

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

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

Die GridView enthält einige untergeordnete Elemente von MyLinearLayout. Dies ist das Layout

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