グリッドビューの高さが切り取られます


124

gridview内に8つのアイテムを表示しようとしています。残念ながら、グリッドビューの高さは常に小さすぎるため、最初の行と2番目の行の一部しか表示されません。

設定android:layout_height="300dp"はそれを動作させます。wrap_でcontentあり、fill_parent明らかにそうではありません。

私のグリッドビュー:

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

私のアイテムのリソース:

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

この問題は、垂直方向のスペースの不足とは関係がないようです。

私に何ができる ?


回答:


351

(多すぎる)研究の後、私はニール・クラフトの素晴らしい答えに出会いました

彼のために彼の作品を適応させることはとてもGridView簡単です。

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

次のようにレイアウトに含めます。

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

最後に、拡張するように要求するだけです。

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

20
このソリューションはメモリ効率が悪いため、セルが画像の場合、アプリがクラッシュします。このソリューションは、スクロールビューにフルグリッドビューの高さを伝え、下に移動できるようにしますが、問題は、リサイクルを使用せずにすべてをレンダリングすることです。200アイテム以上は動作しませんでした。
マリアーノラトーレ2013年

7
@adampこれには便利なケースがあると思います。2D配列に表示するアイテムの数が限られている場合、この種のGridViewを使用すると、なんらかのカスタム/動的なTableLayoutを作成するよりも簡単に見えますか?
greg7gkb 2013年

5
私にはうまくいきません、私はExpandableHeightGridViewをScrollViewの下に置きました、それは最後のビューをカットします。
Chirag Nagariya 2013

3
@taconeこの種類の問題には、フレームワーク、サポートライブラリ、およびその他のオープンソースコードでWeb全体に容易に利用できる、より優れた解決策がいくつかあります。それらをGridLayoutに追加します(GridViewではありません。GridLayoutはサポートライブラリでも利用できます)TableLayoutなど。
adamp 2014年

11
@adampこれが良くない場合は、考えられる最良の解決策で回答を追加してください
aleb

34

@taconeからの回答を使用して機能することを確認した後、コードを短くしてみることにしました。これが私の結果です。PS:これは、taconesの回答でブール値を「展開」して常に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();
    }
}

しかし待ってください-これはまだメモリ使用の問題を抱えています。もうリサイクルしていませんよね?
Fattie

6

私のために機能した別の同様のアプローチは、1つの行の高さを計算してから、静的データ(ページネーションに適合させることができます)を使用して、行の数を計算し、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);
}

このコードは、アダプターの設定後、GridViewが描画されたときに使用します。そうしないと、高さが0になります。

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

1
これは私にとってはうまくいきました-私はListView内で多数のGridViewを使用しています。それが悪い考えであるかどうかはわかりません。大規模なデータセットでパフォーマンスを調査する必要があります。しかし、とにかく、コードをありがとう。しかし、1つずれたエラーがあると思います-私は使用しなければなりませんでしたint rows = items / columns + 1;
Andrew

以下のandroid os 5.0の場合、このエラーが発生しますjava.lang.ClassCastException: android.widget.RelativeLayout$LayoutParams cannot be cast to android.widget.AbsListView$LayoutParams
silverFoxA

ViewGroup.LayoutParams params = gridView.getLayoutParams(); はNullPointerExceptionをスローします
Luke Allison

4

taconesが役立つ回答を見つけたので、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
称賛の男。xamarin.androidで最適に動作します
Suchith

0

AT_MOSTの高さを計算し、測定に設定するだけです。ここでは、GridView Scrollは機能しません。垂直スクロールビューを明示的に使用する必要があります。

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

この方法は、GridViewコントロールのためにスクロールを取得するのに役立ちますです
Suchith
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.