【Android】ScrollView内に配置したGridViewの高さをwrap_contentで指定する

諸事情あって、ScrollView の中に GridView を配置するようなレイアウトのアプリ画面を作成していたのですが、この GridView のスクロールを禁止して常にすべてのアイテムが展開された状態かつ、高さを wrap_content で指定したかったのでその手順のまとめです。

Android 標準の GridView では、上記のような環境で、要素の高さを android:layout_height="wrap_content" と指定すると、一列目のみが表示され、二列目以降の要素はスクロールするようなレイアウトになってしまいます。
が、ScrollView の中でさらにスクロールするような要素は置きたくないし、そもそも GridView の要素はすべて見えるようにしたい!ということで、修正しました。

 

参考にさせていただいた記事はこちら。

AndroidのScrollViewの中のGridViewのlayout_heightが伸び縮みしないのを独自Viewで克服 · GitHub
https://gist.github.com/mistrydarshan99/d64966381331967e39cd

参考に…というか、コードをそのまま まるっと採用させていただきました。

GridView をカスタマイズした独自 View のコードはこちら。
なお、ファイル名は ExpandableHeightGridView.java としましたが、変更しても問題ありません。

package com.cpointlab.example.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.GridView;

/**
 * ScrollViewの中のGridViewでも高さを可変にする
 * http://stackoverflow.com/questions/8481844/gridview-height-gets-cut
 */
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;
    }
}

パッケージ名は適宜環境に合わせて変更してください。
こちらのファイルをプロジェクトに追加したら、標準の GridView と置き換えます。

まず。レイアウトファイルのサンプルコードがこちら。

<ScrollView
    android:id="@+id/sc_spots"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:fillViewport="true" >

    <com.cpointlab.example.view.ExpandableHeightGridView
        android:id="@+id/gridView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:verticalSpacing="10dp"
        android:horizontalSpacing="10dp"
        android:isScrollContainer="false"
        android:numColumns="3"
        android:stretchMode="columnWidth" />
</ScrollView>

GridView を com.cpointlab.example.view.ExpandableHeightGridView という View と置き換えています。
この時、10行目で高さを android:layout_height="wrap_content" で指定しています。

次に、Activity 内のコードを下記のように変更します。

ExpandableHeightGridView gridView = getView().findViewById(R.id.gridView);
gridView.setExpanded(true);
gridView.setAdapter(adapter);
adapter.notifyDataSetChanged();

Adapter の定義については割愛しておりますが、変更はなかったのでそのままでOKです。

変更点は以上です。
あとは、アプリを再ビルドして実行します。
更新し忘れなどがなければ、問題なくスクロールなしですべての要素が既に展開された GridView が表示されているはずです。

最悪、高さを 400dp などの固定値で指定すれば、同じことができなくもないのですが、要素が増えたときや他の端末で見たときにレイアウトが崩れる危険性があったので、この方法を採用しました。
そもそも、この方法の方が簡単かつ便利ですしね。

 

以上、Android アプリで ScrollView の中に配置した GridView の要素を全て展開し、かつ高さを wrap_content で指定する方法でした。
ご参考になれば幸いです。

>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG