2011-12-12 15 views
106

Sto provando a visualizzare 8 elementi all'interno di una griglia. Purtroppo, l'altezza della griglia è sempre troppo piccola, quindi mostra solo la prima riga e una piccola parte del secondo.L'altezza della griglia viene tagliata

L'impostazione android:layout_height="300dp" funziona. wrap_ content e fill_parent apparentemente no.

La mia vista 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" /> 

Mie risorsa:

<?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 correlato alla mancanza di spazio verticale.

Cosa posso fare?

risposta

314

Dopo (troppo) ricerche, sono inciampato su the excellent answer of Neil Traft.

L'adattamento del suo lavoro per il GridView è stato 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; 
    } 
} 

includerlo nel 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 è solo bisogno di chiedere di ampliare:

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

Mi chiedevo perché il mio GridView era così breve poi ho trovato questo! funziona alla grande :) grazie! – AndroidNoob

+0

Ottima soluzione! Tuttavia, il valore booleano espanso è probabilmente ridondante. Potresti semplicemente controllare se l'altezza dei parametri di layout è impostata su "wrap_content" invece di controllare il valore booleano espanso. –

+0

Anche il mio commento precedente richiederebbe la rimozione della riga 'params.height = getMeasuredHeight();' –

0

Basta calcolare il altezza per AT_MOST e impostato su su misura. Qui GridView Scroll non funzionerà così. È necessario utilizzare la Vista verticale di scorrimento 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); 
} 
+0

Questo metodo ti aiuta a scorrere per GridView – Suchith

5

Un altro approccio simile che ha lavorato per me, è quello di calcolare l'altezza per una riga e poi con dati statici (si può adattarlo a impaginare) è possibile calcolare il numero di righe che avete e ridimensionare l'altezza GridView con facilità .

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 il GridView è disegnato o si otterrà height = 0.

+1

Questo ha funzionato bene per me: sto utilizzando un gruppo di GridViews all'interno di un ListView. Non sono sicuro se questa sia 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 usare 'int rows = items/columns + 1;' – Andrew

+0

per sotto Android os 5.0 ottengo questo errore 'java.lang .ClassCastException: android.widget.RelativeLayout $ LayoutParams non può essere lanciato su android.widget.AbsListView $ LayoutParams' – silverFoxA

+0

risposta superba !!! buon esempio di riusabilità piuttosto che reinventare la ruota –

22

Dopo aver utilizzato la risposta da @tacone e fare in modo ha funzionato, ho deciso per provare ad abbreviare il codice. Questo è il mio risultato PS: È l'equivalente di avere il booleano "espanso" nella risposta tacona sempre impostato 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(); 
    } 
} 
+0

Grazie funziona benissimo :) – Tony

+0

Ma aspetta - questo ancora soffre il problema dell'uso della memoria; non stai più riciclando, giusto? – Fattie

+0

Sì, questo funziona allo stesso modo del codice @ tacone –

4

tacones Trovato risposta utile ... così ho portato in 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

Kudos tizio. Funziona alla grande in xamarin.android – Suchith

Problemi correlati