web-dev-qa-db-ja.com

アイテムが追加されたときに高さを調整するGridViewを作成する方法

GridViewのチェックボックスを使用して、動的に成長する文字列のリストを表示しようとしています。GridViewはTableLayoutにあります。

これらの「チェックボックス」文字列を連続して表示できます。ユーザーがGridViewに新しい文字列を動的に追加できるようにすると、問題が発生します。

文字列のリストを受け取るカスタムアダプターを作成しました。 n個の文字列があるとします。アダプターは、アイテム数に対して「n + 1」を返します。 getViewでは、次を返します。

  • 最初のn個の項目のCheckBoxとEditTextを持つLinearLayoutを持つビュー
  • 「n + 1」番目の項目に「+」キャプションが付いたシンプルなボタンを備えたLinearLayout.

ここまでは順調ですね。 [+]ボタンをクリックすると、空の文字列が文字列のリストに追加され、アダプターでnotifyDataSetChangedが呼び出されます。

GridViewは、もう1つのアイテムで再描画します。ただし、元の高さを維持し、垂直スクロールバーを作成します。 GridViewの高さを拡張したい(つまり、画面上のスペースをより多く使用してすべてのアイテムを表示したい)。

画面をTableLayoutではなく垂直のLinearLayoutに変更しようとしましたが、結果は同じです。

画面のレイアウトは次のとおりです。

<ScrollView xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:scrollbars="none">
<LinearLayout
    Android:layout_width="fill_parent"
    Android:layout_height="wrap_content"
    Android:orientation="vertical"
    >

    <!-- other lines omitted -->

    <LinearLayout Android:layout_width="fill_parent" 
                  Android:layout_height="wrap_content" >
        <TextView
            Android:layout_width="wrap_content" 
            Android:layout_height="wrap_content"
            Android:text="@string/wine_rack_explanation"
            Android:layout_gravity="center_vertical" />
          <GridView
            Android:layout_width="fill_parent" 
            Android:layout_height="wrap_content"
            Android:id="@+id/gvRack"
            Android:columnWidth="90dp"    
            Android:numColumns="auto_fit" />
    </LinearLayout>

<!-- other lines omitted -->

</LinearLayout>
</ScrollView>

アダプタのチェックボックス+文字列アイテムは、次のように定義されます。

<LinearLayout
  xmlns:Android="http://schemas.Android.com/apk/res/Android"
  Android:orientation="horizontal"

  Android:layout_width="wrap_content"
  Android:layout_height="wrap_content">
    <CheckBox Android:layout_width="wrap_content"
              Android:layout_height="wrap_content"
              Android:id="@+id/cbCoordinate"
              Android:checked="true"
              />
    <EditText Android:id="@+id/txtCoordinate"
              Android:layout_width="wrap_content"
              Android:layout_height="wrap_content" />
</LinearLayout>

「+」ボタン項目は次のように定義されます。

<LinearLayout
  xmlns:Android="http://schemas.Android.com/apk/res/Android"
  Android:orientation="horizontal"
  Android:layout_width="wrap_content"
  Android:layout_height="wrap_content">

    <Button Android:id="@+id/btnAddBottle"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:text="@string/add_bottle_caption" />
</LinearLayout>

アイテムが追加された後、GridViewでinvalidateまたはinvalideViewsを呼び出そうとしました。 TableLayoutおよびTableRow(画面の前のレイアウト)で無効化とも呼ばれます。失敗。

GridViewが高さの拡張を拒否する理由は何ですか?

(GridView以外のビューグループを完全に使用できることに注意してください)

27
Timores

このコードを使用

public class MyGridView  extends GridView {

    public MyGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyGridView(Context context) {
        super(context);
    }

    public MyGridView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
                MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);
    }
}
52
Raj008

私はこのようにしました:

このコードは、childnumberに従ってGridViewの高さを設定します。

注:ここで5は列の数です。

private void setDynamicHeight(GridView gridView) {
        ListAdapter gridViewAdapter = gridView.getAdapter();
        if (gridViewAdapter == null) {
            // pre-condition
            return;
        }

        int totalHeight = 0;
        int items = gridViewAdapter.getCount();
        int rows = 0;

        View listItem = gridViewAdapter.getView(0, null, gridView);
        listItem.measure(0, 0);
        totalHeight = listItem.getMeasuredHeight();

        float x = 1;
        if( items > 5 ){
            x = items/5;
            rows = (int) (x + 1);
            totalHeight *= rows;
        }

        ViewGroup.LayoutParams params = gridView.getLayoutParams();
        params.height = totalHeight;
        gridView.setLayoutParams(params);
    }

これがお役に立てば幸いです。

8
Hiren Patel

GridViewでonMeasure()が呼び出されたときに、heightModeがMeasureSpec.UNSPECIFIEDの場合、gridviewは含まれているすべての要素(およびいくつかのパディング)と同じ高さになります。

これを確実にするために、GridViewを拡張し、次のオーバーライドを含むクイックカスタムビューを作成できます。

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, MeasureSpec.UNSPECIFIED);
    }
4
Graham

これは私のために働いています:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/root"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:background="@drawable/background" >

        <!-- MORE LAYOUTS IF YOU WANT -->

    <ScrollView
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:layout_weight="1"
    Android:fillViewport="true" >

    <RelativeLayout
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content" >

                <!-- MORE LAYOUTS IF YOU WANT -->

       <GridView
            Android:id="@+id/gridview"
            Android:layout_width="wrap_content"
            Android:layout_height="match_parent"
            Android:layout_marginBottom="10dp"
            Android:layout_marginLeft="20dp"
            Android:layout_marginRight="20dp"
            Android:layout_marginTop="5dp"
            Android:gravity="center"
            Android:horizontalSpacing="10dp"
            Android:numColumns="auto_fit"
            Android:stretchMode="columnWidth"
            Android:verticalSpacing="10dp" >
       </GridView>

             <!-- MORE LAYOUTS IF YOU WANT -->

    </RelativeLayout>

    </ScrollView>

</RelativeLayout>
4
Neonigma

グラハムのソリューションは私にはうまくいきませんでした。ただし、これは(もう少しハッキングがあります)行いました: https://stackoverflow.com/a/8483078/479478

1
Eric Chen

これは私のために働いています

public class MyGridView extends GridView {
    public MyGridView(Context context) {
        super(context);
    }

    public MyGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyGridView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        // set childs height to same value as child that has highest value
        for(int i=0; i<getChildCount(); i++) {
            MyLinearLayout child = (MyLinearLayout) getChildAt(i);
            AbsListView.LayoutParams params = (AbsListView.LayoutParams) child.getLayoutParams();
            params.height = MyLinearLayout.maxHeight;
            child.setLayoutParams(params);
        }

        // calculate total height and apply to the grid
        double numRow = Math.ceil((double) getCount() / (double) getNumColumns());
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) this.getLayoutParams();
        params.height = (int) numRow *  MyLinearLayout.maxHeight;
        this.setLayoutParams(params);

        // invalidate after change grid's height
        this.invalidate();
    }
}

MyLinearLayoutクラス

public class MyLinearLayout extends LinearLayout {
    public static int maxHeight = 0;

    public MyLinearLayout(Context context) {
        super(context);
    }

    public MyLinearLayout(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MyLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (maxHeight<this.getMeasuredHeight()) maxHeight=this.getMeasuredHeight();
    }
}

GridViewにはMyLinearLayoutのいくつかの子が含まれており、これがレイアウトです

<?xml version="1.0" encoding="utf-8"?>
<com.mysystem.view.MyLinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
              Android:layout_width="100dp"
              Android:layout_height="100dp"
              Android:background="#ddd"
              Android:padding="0.5dp"
              Android:layout_gravity="top"
              Android:gravity="center_horizontal"
              Android:orientation="vertical">

    <LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:background="#fff"
        Android:padding="20dp"
        Android:orientation="vertical">

        <ImageView
            Android:id="@+id/img_menu"
            Android:layout_width="30dp"
            Android:layout_gravity="center_horizontal"
            Android:layout_height="30dp"
            Android:layout_marginTop="5dp"/>

        <TextView
            Android:id="@+id/tv_menu"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:layout_marginTop="5dp"
            Android:textAlignment="center"
            Android:textColor="#000"
            Android:text="Title"
            Android:textSize="10sp"/>

    </LinearLayout>
</com.mysystem.view.MyLinearLayout>