Die Rasteransichtshöhe wird abgeschnitten

124

Ich versuche, 8 Elemente in einer Rasteransicht anzuzeigen. Leider ist die Höhe der Rasteransicht immer zu gering, sodass nur die erste Zeile und ein kleiner Teil der zweiten angezeigt werden.

Durch die Einstellung android:layout_height="300dp"funktioniert es. wrap_ contentund fill_parentanscheinend nicht.

Meine Rasteransicht:

<GridView
    android:id="@+id/myId"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:horizontalSpacing="2dp"
    android:isScrollContainer="false"
    android:numColumns="4"
    android:stretchMode="columnWidth"
    android:verticalSpacing="20dp" />

Meine Artikel Ressource:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:minHeight="?android:attr/listPreferredItemHeight" >

    <ImageView
        android:id="@+id/appItemIcon"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:src="@android:drawable/ic_dialog_info"
        android:scaleType="center" />      

    <TextView
        android:id="@+id/appItemText"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="My long application name"
        android:gravity="center_horizontal"
        android:textAppearance="?android:attr/textAppearanceSmall" />

</LinearLayout>

Das Problem scheint nicht mit einem Mangel an vertikalem Raum zu tun zu haben.

Was kann ich tun ?

Tacone
quelle

Antworten:

351

Nach (zu viel) Recherche bin ich auf die hervorragende Antwort von Neil Traft gestoßen .

Die Anpassung seiner Arbeit an das GridViewwar kinderleicht.

ExpandableHeightGridView.java:

package com.example;
public class ExpandableHeightGridView extends GridView
{

    boolean expanded = false;

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

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

    public ExpandableHeightGridView(Context context, AttributeSet attrs,
            int defStyle)
    {
        super(context, attrs, defStyle);
    }

    public boolean isExpanded()
    {
        return expanded;
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        // HACK! TAKE THAT ANDROID!
        if (isExpanded())
        {
            // Calculate entire height by providing a very large height hint.
            // View.MEASURED_SIZE_MASK represents the largest height possible.
            int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK,
                    MeasureSpec.AT_MOST);
            super.onMeasure(widthMeasureSpec, expandSpec);

            ViewGroup.LayoutParams params = getLayoutParams();
            params.height = getMeasuredHeight();
        }
        else
        {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    public void setExpanded(boolean expanded)
    {
        this.expanded = expanded;
    }
}

Fügen Sie es wie folgt in Ihr Layout ein:

<com.example.ExpandableHeightGridView
    android:id="@+id/myId"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:horizontalSpacing="2dp"
    android:isScrollContainer="false"
    android:numColumns="4"
    android:stretchMode="columnWidth"
    android:verticalSpacing="20dp" />

Zuletzt müssen Sie es nur bitten, um zu erweitern:

mAppsGrid = (ExpandableHeightGridView) findViewById(R.id.myId);
mAppsGrid.setExpanded(true);
Tacone
quelle
20
Diese Lösung ist nicht speichereffizient und die App stürzt ab, wenn die Zellen Bilder sind. Diese Lösung teilt der Bildlaufansicht mit, wie hoch die vollständige Rasteransicht ist, damit sie nach unten gehen kann. Das Problem besteht jedoch darin, dass alles ohne Recycling gerendert wird. Es konnten nicht mehr als 200 Gegenstände funktionieren.
Mariano Latorre
7
@adamp Ich denke, es gibt nützliche Fälle dafür. Wenn Sie eine begrenzte Anzahl von Elementen in einem 2D-Array anzeigen möchten, scheint die Verwendung dieser Art von GridView einfacher zu sein als der Versuch, eine Art benutzerdefiniertes / dynamisches TableLayout zu erstellen, nicht wahr?
Greg7gkb
5
Funktioniert bei mir nicht, ich habe ExpandableHeightGridView unter ScrollView gestellt, es schneidet die letzte Ansicht.
Chirag Nagariya
3
@tacone Es gibt eine Reihe besserer Lösungen für diese Art von Problem, die im Framework, in der Support-Bibliothek und in anderem Open Source-Code im Internet verfügbar sind. Die einfachste davon kann ein einfaches For-Loop-Abrufen von Ansichten von einem Adapter oder anderswo sein Hinzufügen zu einem GridLayout (nicht GridView; GridLayout ist auch in der Support-Bibliothek verfügbar) TableLayout oder ähnliches.
Adamp
11
@adamp Wenn dies nicht gut ist, fügen Sie bitte Ihre Antwort mit der besten Lösung hinzu, die Sie sich
vorstellen
34

Nachdem ich die Antwort von @tacone verwendet und sichergestellt hatte, dass sie funktionierte, beschloss ich, den Code kurzzuschließen. Das ist mein Ergebnis. PS: Es ist das Äquivalent dazu, dass die boolesche "erweiterte" Antwort in Tacones immer auf "true" gesetzt ist.

public class StaticGridView extends GridView {

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

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

    public StaticGridView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK, MeasureSpec.AT_MOST));
        getLayoutParams().height = getMeasuredHeight();
    }
}
Jacob R.
quelle
Aber warten Sie - dies leidet immer noch unter dem Problem der Speichernutzung. Sie recyceln nicht mehr richtig?
Fattie
6

Ein anderer ähnlicher Ansatz, der für mich funktioniert hat, besteht darin, die Höhe für eine Zeile zu berechnen und dann mit statischen Daten (Sie können sie an die Paginierung anpassen) zu berechnen, wie viele Zeilen Sie haben, und die Größe der GridView-Höhe einfach zu ändern.

    private void resizeGridView(GridView gridView, int items, int columns) {
    ViewGroup.LayoutParams params = gridView.getLayoutParams();
    int oneRowHeight = gridView.getHeight();
    int rows = (int) (items / columns);
    params.height = oneRowHeight * rows;
    gridView.setLayoutParams(params);
}

Verwenden Sie diesen Code, nachdem Sie den Adapter eingestellt haben und wenn die GridView gezeichnet wird, oder Sie erhalten height = 0.

gridView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (!gridViewResized) {
                    gridViewResized = true;
                    resizeGridView(gridView, numItems, numColumns);
                }
            }
        });
Pelanes
quelle
1
Das hat bei mir gut funktioniert - ich verwende eine Reihe von GridViews in einer ListView. Ich bin mir nicht sicher, ob das noch eine schlechte Idee ist oder nicht - ich muss die Leistung mit einem großen Datensatz untersuchen. Aber trotzdem danke für den Code. Ich denke, es gibt einen Fehler nach dem anderen - ich musste ihn verwendenint rows = items / columns + 1;
Andrew
für unter Android java.lang.ClassCastException: android.widget.RelativeLayout$LayoutParams cannot be cast to android.widget.AbsListView$LayoutParams
OS
ViewGroup.LayoutParams params = gridView.getLayoutParams (); wirft eine NullPointerException
Luke Allison
4

Gefundene Tacones antworten hilfreich ... also habe ich es auf C # (Xamarin) portiert

public class ExpandableHeightGridView: GridView
{
    bool _isExpanded = false;

    public ExpandableHeightGridView(Context context) : base(context)
    {            
    }

    public ExpandableHeightGridView(Context context, IAttributeSet attrs) : base(context, attrs)
    {            
    }

    public ExpandableHeightGridView(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
    {            
    }

    public bool IsExpanded
    {
        get { return _isExpanded; }

        set { _isExpanded = value;  }
    }

    protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        // HACK! TAKE THAT ANDROID!
        if (IsExpanded)
        {
            // Calculate entire height by providing a very large height hint.
            // View.MEASURED_SIZE_MASK represents the largest height possible.
            int expandSpec = MeasureSpec.MakeMeasureSpec( View.MeasuredSizeMask, MeasureSpecMode.AtMost);
            base.OnMeasure(widthMeasureSpec,expandSpec);                

            var layoutParameters = this.LayoutParameters;
            layoutParameters.Height = this.MeasuredHeight;
        }
        else
        {
            base.OnMeasure(widthMeasureSpec,heightMeasureSpec);    
        }
    }
}
spaceMonster
quelle
1
Ein dickes Lob, Alter. Funktioniert hervorragend in xamarin.android
Suchith
0

Berechnen Sie einfach die Höhe für AT_MOST und setzen Sie auf on Measure. Hier funktioniert GridView Scroll nicht so. Die vertikale Bildlaufansicht muss explizit verwendet werden.

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

     if (getLayoutParams().height == LayoutParams.WRAP_CONTENT) {

         heightSpec = MeasureSpec.makeMeasureSpec(
                        Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
     }
     else {
         // Any other height should be respected as is.
         heightSpec = heightMeasureSpec;
     }

     super.onMeasure(widthMeasureSpec, heightSpec);
 }
Uday Sravan K.
quelle
Ist diese Methode hilft Ihnen beim Scrollen für GridView
Suchith