Ketinggian Gridview dipotong

125

Saya mencoba untuk menampilkan 8 item di dalam gridview. Sayangnya, ketinggian tampilan kisi selalu terlalu kecil, sehingga hanya menampilkan baris pertama, dan sebagian kecil dari baris kedua.

Pengaturan android:layout_height="300dp"membuatnya bekerja. wrap_ contentdan fill_parentternyata tidak.

Tampilan kisi saya:

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

Sumber daya item saya:

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

Masalah tersebut sepertinya tidak terkait dengan kurangnya ruang vertikal.

Apa yang dapat saya ?

tacone
sumber
Apakah ini menjawab pertanyaan Anda? Cara memiliki GridView yang menyesuaikan tingginya saat item ditambahkan
Shivam Agarwal

Jawaban:

351

Setelah (terlalu banyak) penelitian, saya menemukan jawaban yang sangat bagus dari Neil Traft .

Menyesuaikan karyanya untuk yang GridViewsudah mati sangat mudah.

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

Sertakan dalam tata letak Anda seperti ini:

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

Terakhir Anda hanya perlu memintanya untuk memperluas:

mAppsGrid = (ExpandableHeightGridView) findViewById(R.id.myId);
mAppsGrid.setExpanded(true);
tacone
sumber
20
solusi ini tidak hemat memori dan aplikasi akan mogok jika sel adalah gambar. Solusi ini memberi tahu scrollview berapa tinggi tampilan grid penuh sehingga bisa turun, tetapi masalahnya adalah melakukannya membuat semuanya tanpa menggunakan daur ulang. Tidak lebih dari 200 item bisa bekerja.
Mariano Latorre
7
@adamp Saya pikir ada kasus yang berguna untuk ini. Jika Anda memiliki jumlah item terbatas untuk ditampilkan ke dalam array 2d, menggunakan jenis GridView ini tampaknya lebih mudah daripada mencoba membuat beberapa jenis TableLayout kustom / dinamis, bukan?
greg7gkb
5
Tidak berfungsi untuk saya, saya telah meletakkan ExpandableHeightGridView di bawah ScrollView, ini memotong tampilan terakhir.
Chirag Nagariya
3
@tacone Ada sejumlah solusi yang lebih baik untuk masalah semacam ini yang tersedia dalam kerangka kerja, pustaka dukungan, dan kode sumber terbuka lainnya di seluruh web, yang paling mudah adalah dengan menarik Views secara berulang-ulang dari adaptor atau di tempat lain dan menambahkannya ke GridLayout, (bukan GridView; GridLayout juga tersedia di lib dukungan) TableLayout atau yang serupa.
adamp
11
@adamp Jika ini tidak bagus, tambahkan jawaban Anda dengan solusi terbaik yang dapat Anda pikirkan
aleb
34

Setelah menggunakan jawaban dari @tacone dan memastikannya berhasil, saya memutuskan untuk mencoba mempersingkat kodenya. Ini hasil saya. PS: Ini setara dengan meminta boolean "diperluas" dalam jawaban nada yang selalu disetel ke benar.

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
sumber
Tapi tunggu - ini masih mengalami masalah penggunaan memori; kamu tidak mendaur ulang lagi kan?
Fattie
6

Pendekatan serupa lainnya yang berhasil untuk saya, adalah menghitung tinggi untuk satu baris dan kemudian dengan data statis (Anda dapat menyesuaikannya menjadi paginasi) Anda dapat menghitung berapa banyak baris yang Anda miliki dan mengubah ukuran tinggi GridView dengan mudah.

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

Gunakan kode ini setelah mengatur adaptor dan ketika GridView digambar atau Anda akan mendapatkan tinggi = 0.

gridView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (!gridViewResized) {
                    gridViewResized = true;
                    resizeGridView(gridView, numItems, numColumns);
                }
            }
        });
Pelanes
sumber
1
Ini bekerja dengan baik untuk saya - saya menggunakan banyak GridView di dalam ListView. Tidak yakin apakah itu ide yang buruk atau tidak - perlu menyelidiki kinerja dengan kumpulan data yang besar. Tapi terlepas, terima kasih untuk kodenya. Saya pikir ada kesalahan off-by-one - saya harus menggunakanint rows = items / columns + 1;
Andrew
untuk di bawah android os 5.0 saya mendapatkan kesalahan inijava.lang.ClassCastException: android.widget.RelativeLayout$LayoutParams cannot be cast to android.widget.AbsListView$LayoutParams
silverFoxA
ViewGroup.LayoutParams params = gridView.getLayoutParams (); melempar NullPointerException
Luke Allison
4

Found tacones answer membantu ... jadi saya porting ke 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);    
        }
    }
}
spaceMonster
sumber
1
Kudos dude. Bekerja dengan baik di xamarin.android
Suchith
0

Cukup hitung tinggi untuk AT_MOST dan setel ke ukuran. Di sini, GridView Scroll tidak akan berfungsi. Perlu menggunakan Tampilan Scroll Vertikal secara eksplisit.

 @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.
sumber
Apakah metode ini membantu Anda mendapatkan pengguliran untuk GridView
Suchith