L'altezza di Gridview viene ridotta


125

Sto cercando di visualizzare 8 elementi all'interno di un gridview. Purtroppo, l'altezza della griglia è sempre troppo piccola, quindi mostra solo la prima riga e una piccola parte della seconda.

L'impostazione lo android:layout_height="300dp"fa funzionare. wrap_ contente fill_parentapparentemente no.

La mia visualizzazione a griglia:

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

Risorsa I miei articoli:

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

Il problema non sembra legato alla mancanza di spazio verticale.

Cosa posso fare ?


Risposte:


351

Dopo (troppe) ricerche, sono incappato nell'eccellente risposta di Neil Traft .

Adattare il suo lavoro per il film GridViewè stato estremamente facile.

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

Includilo nel tuo layout in questo modo:

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

Infine, devi solo chiedergli di espandere:

mAppsGrid = (ExpandableHeightGridView) findViewById(R.id.myId);
mAppsGrid.setExpanded(true);

20
questa soluzione non è efficiente in termini di memoria e l'app andrà in crash se le celle sono immagini. Questa soluzione dice allo scrollview qual è l'altezza dell'intera griglia in modo che possa scendere, ma il problema è che per farlo rende tutto senza riciclo. Non più di 200 articoli potrebbero funzionare.
Mariano Latorre

7
@adamp Penso che ci siano casi utili per questo. Se hai un numero limitato di elementi da visualizzare in un array 2d, l'uso di questo tipo di GridView sembra più facile che provare a creare un qualche tipo di TableLayout personalizzato / dinamico, no?
greg7gkb

5
Non funziona per me, ho messo ExpandableHeightGridView sotto ScrollView, taglia l'ultima vista.
Chirag Nagariya

3
@tacone Esistono numerose soluzioni migliori per questo tipo di problema prontamente disponibili nel framework, nella libreria di supporto e in altro codice open source sul Web, la più semplice delle quali può essere un semplice ciclo for che estrae le viste da un adattatore o altrove e aggiungendoli a un GridLayout, (non GridView; GridLayout è anche disponibile nella libreria di supporto) TableLayout o simili.
adamp

11
@adamp Se questo non va bene, aggiungi la tua risposta con la migliore soluzione che ti viene in mente
aleb

34

Dopo aver usato la risposta di @tacone e assicurandomi che funzionasse, ho deciso di provare ad abbreviare il codice. Questo è il mio risultato. PS: è l'equivalente di avere la risposta booleana "espansa" in tacones sempre impostata su true.

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

Ma aspetta: questo soffre ancora del problema dell'utilizzo della memoria; non stai riciclando più giusto?
Fattie

6

Un altro approccio simile che ha funzionato per me, è calcolare l'altezza di una riga e poi con dati statici (puoi adattarli per impaginare) puoi calcolare quante righe hai e ridimensionare facilmente l'altezza di GridView.

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

Usa questo codice dopo aver impostato l'adattatore e quando viene disegnato GridView o otterrai altezza = 0.

gridView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (!gridViewResized) {
                    gridViewResized = true;
                    resizeGridView(gridView, numItems, numColumns);
                }
            }
        });

1
Questo ha funzionato bene per me: sto usando un sacco di GridViews all'interno di un ListView. Non sono sicuro che sia ancora una cattiva idea o meno: è necessario esaminare le prestazioni con un set di dati di grandi dimensioni. Ma a prescindere, grazie per il codice. Penso che ci sia un errore off-by-one però - ho dovuto usareint rows = items / columns + 1;
Andrew

per il sistema java.lang.ClassCastException: android.widget.RelativeLayout$LayoutParams cannot be cast to android.widget.AbsListView$LayoutParams
operativo

ViewGroup.LayoutParams params = gridView.getLayoutParams (); lancia una NullPointerException
Luke Allison

4

Trovato tacones risposta utile ... quindi l'ho portato su C # (Xamarin)

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

1
Complimenti amico. Funziona alla grande in xamarin.android
Suchith

0

Calcola semplicemente l'altezza per AT_MOST e impostala su misura. Qui GridView Scroll non funzionerà così. È necessario utilizzare la visualizzazione a scorrimento verticale in modo esplicito.

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

Questo metodo ti aiuta a ottenere lo scorrimento per GridView
Suchith
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.