Gridview yüksekliği kesiliyor


125

Bir ızgara görünümünde 8 öğe görüntülemeye çalışıyorum. Ne yazık ki, ızgara görünümü yüksekliği her zaman çok azdır, bu nedenle yalnızca ilk satırı ve ikincinin küçük bir bölümünü gösterir.

Ayar android:layout_height="300dp", çalışmasını sağlar. wrap_ contentvefill_parent görünüşe göre değil.

Izgara görünümüm:

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

Öğelerim kaynağı:

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

Sorun dikey alan eksikliği ile ilgili görünmüyor.

Ne yapabilirim ?


Yanıtlar:


351

(Çok fazla) araştırmadan sonra , Neil Traft'ın mükemmel cevabına rastladım .

Çalışmalarını uyarlamak GridViewçok kolay oldu.

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

Düzeninize şu şekilde ekleyin:

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

Son olarak, genişletmesini istemeniz yeterlidir:

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

20
bu çözüm bellek açısından verimli değildir ve hücreler görüntü ise uygulama çökecektir. Bu çözüm, kaydırma görünümüne tam ızgara görünümünün yüksekliğinin ne olduğunu söyler, böylece aşağı inebilir, ancak sorun şu ki, bunu yapmak, her şeyi geri dönüşümü kullanmadan işler. 200'den fazla öğe işe yaramaz.
Mariano Latorre

7
@adamp Bunun için yararlı durumlar olduğunu düşünüyorum. Bir 2d dizisinde gösterilecek sınırlı sayıda öğeniz varsa, bu tür GridView kullanmak, bir tür özel / dinamik TableLayout oluşturmaya çalışmaktan daha kolay görünüyor, değil mi?
greg7gkb

5
Benim için çalışmıyor, ExpandableHeightGridView'ı ScrollView altına koydum, son görünümü kesiyor.
Chirag Nagariya

3
@tacone Bu tür bir sorun için çerçevede, destek kitaplığında ve web üzerindeki diğer açık kaynak kodlarında kolayca bulunabilen bir dizi daha iyi çözüm vardır; bunların en kolayı, Görünümleri bir adaptörden veya başka bir yerden çekmek ve bunları bir GridLayout'a eklemek (GridView değil; GridLayout, destek kitaplığında da mevcuttur) TableLayout veya benzeri.
adamp

11
@adamp Bu iyi değilse lütfen aklınıza gelebilecek en iyi çözümle cevabınızı ekleyin
aleb

34

@Tacone'nin cevabını kullandıktan ve çalıştığından emin olduktan sonra, kodu kısaltmaya karar verdim. Bu benim sonucum. Not: Bu, tacones yanıtında mantıksal "genişletilmiş" değerinin her zaman doğru olarak ayarlanmasıyla eşdeğerdir.

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

Ama bekleyin - bu hala bellek kullanımı sorununu yaşıyor; artık geri dönüşüm yapmıyorsun değil mi?
Fattie

6

Benim için işe yarayan başka bir benzer yaklaşım, bir satırın yüksekliğini hesaplamaktır ve ardından statik verilerle (sayfalandırmaya uyarlayabilirsiniz) kaç satırınız olduğunu hesaplayabilir ve GridView yüksekliğini kolayca yeniden boyutlandırabilirsiniz.

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

Bağdaştırıcıyı ayarladıktan sonra ve GridView çizildiğinde bu kodu kullanın, yoksa yükseklik = 0 alırsınız.

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

1
Bu benim için iyi çalıştı - ListView içinde bir sürü GridView kullanıyorum. Bunun henüz kötü bir fikir olup olmadığından emin değilim - performansı büyük bir veri kümesiyle araştırmanız gerekiyor. Ama ne olursa olsun, kod için teşekkürler. Sanırım bir defaya mahsus bir hata var - kullanmak zorunda kaldımint rows = items / columns + 1;
Andrew

android os java.lang.ClassCastException: android.widget.RelativeLayout$LayoutParams cannot be cast to android.widget.AbsListView$LayoutParams
5.0'ın

ViewGroup.LayoutParams params = gridView.getLayoutParams (); bir NullPointerException atıyor
Luke Allison

4

Tacones cevabı yararlı buldum ... bu yüzden onu C # 'a taşıdım (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
Tebrikler dostum. Xamarin.android'de harika çalışıyor
Suchith

0

Sadece AT_MOST için yüksekliği hesaplayın ve ölçüye göre ayarlayın. Burada GridView Scroll böyle çalışmayacak. Dikey Kaydırma Görünümünü açıkça kullanmanız gerekir.

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

Bu yöntem, GridView için kaydırmanıza yardımcı oluyor mu
Suchith
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.