我想有一个2x2网格内的按钮。这只是ICS,所以我试图使用新的GridLayout给定。

这是我的布局的XML:

 <?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/favorites_grid"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#00ff00"
    android:rowCount="2"
    android:columnCount="2">
  <Button
      android:text="Cell 0"
      android:layout_row="0"
      android:layout_column="0"
      android:textSize="14dip" />
  <Button
      android:text="Cell 1"
      android:layout_row="0"
      android:layout_column="1"
      android:textSize="14dip" />

  <Button
      android:text="Cell 2"
      android:layout_row="1"
      android:layout_column="0"
      android:textSize="14dip" />
  <Button
      android:text="Cell 3"
      android:layout_row="1"
      android:layout_column="1"
      android:textSize="14dip" />
</GridLayout>

问题是我的视图没有为每一行均匀地拉伸。这导致GridLayout的右侧有很多额外的空间。

我尝试设置layout_gravity="fill_horizontal",但这只适用于该行的最后一个视图。这意味着单元格1会一直延伸,为单元格0提供足够的空间。

如何解决这个问题?


当前回答

我终于找到了解决办法。就像Rotemmiz说的,你必须在之后动态地做。这段代码拉伸按钮以水平填充视图,但同样可以用于垂直填充视图。

public void fillview(android.support.v7.widget.GridLayout gl)
{
    Button buttontemp;

    //Stretch buttons
    int idealChildWidth = (int) ((gl.getWidth()-20*gl.getColumnCount())/gl.getColumnCount());
    for( int i=0; i< gl.getChildCount();i++)
    {
        buttontemp = (Button) gl.getChildAt(i);
        buttontemp.setWidth(idealChildWidth);
    }
}

(20是内部和外部的填充和空白。这可以更普遍地做,但这个要干净得多)

然后可以这样调用:

    android.support.v7.widget.GridLayout gl = (android.support.v7.widget.GridLayout)findViewById(R.id.buttongrid);
    ViewTreeObserver vto = gl.getViewTreeObserver();
    vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {@Override public void onGlobalLayout() 
    {

            android.support.v7.widget.GridLayout gl = (android.support.v7.widget.GridLayout) findViewById(R.id.buttongrid);
            fillview(gl);

            ViewTreeObserver obs = gl.getViewTreeObserver();
            obs.removeGlobalOnLayoutListener(this);
    }});

它必须用一个观察者来完成,因为我们需要在调用视图之前等待视图被绘制。

其他回答

我终于找到了解决办法。就像Rotemmiz说的,你必须在之后动态地做。这段代码拉伸按钮以水平填充视图,但同样可以用于垂直填充视图。

public void fillview(android.support.v7.widget.GridLayout gl)
{
    Button buttontemp;

    //Stretch buttons
    int idealChildWidth = (int) ((gl.getWidth()-20*gl.getColumnCount())/gl.getColumnCount());
    for( int i=0; i< gl.getChildCount();i++)
    {
        buttontemp = (Button) gl.getChildAt(i);
        buttontemp.setWidth(idealChildWidth);
    }
}

(20是内部和外部的填充和空白。这可以更普遍地做,但这个要干净得多)

然后可以这样调用:

    android.support.v7.widget.GridLayout gl = (android.support.v7.widget.GridLayout)findViewById(R.id.buttongrid);
    ViewTreeObserver vto = gl.getViewTreeObserver();
    vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {@Override public void onGlobalLayout() 
    {

            android.support.v7.widget.GridLayout gl = (android.support.v7.widget.GridLayout) findViewById(R.id.buttongrid);
            fillview(gl);

            ViewTreeObserver obs = gl.getViewTreeObserver();
            obs.removeGlobalOnLayoutListener(this);
    }});

它必须用一个观察者来完成,因为我们需要在调用视图之前等待视图被绘制。

关于网格布局的一些技巧。

Default Grid layout works best on min SDK 21+ . GridLayout's height/width should be either fixed or match_parent .It is because Grid layout calculates the height/width of its child, and having the variable height of its own could cause issues in calculation of the exact height. Grid layout ignores the margins on children by default, so we should be using android:useDefaultMargins="true" if we want children to control their margins. To make a dynamic, auto-stretching group of views with Grid layout, either: the parent would be controlling both: the max height of the total group and number of elements in each row or the parent would be controlling the number of columns in each row,and the children will be controlling the total height.

第一个场景的优点是我们可以在组中添加任意数量的孩子,他们都将很好地均匀伸展。缺点是我们得到的是一个固定规模的群体。而内容较大的儿童也占据了固定的空间。

第二个场景的优点是我们可以添加更多的子节点,由子节点决定组的高度。在父元素的顶部附加一个嵌套的滚动视图将使整个元素列表可滚动。 缺点是,儿童控制组的高度和变量高度,可能会导致整个视图看起来混乱。

如果我们稍微调整一下,这两种情况都可以发挥它们的优点,它们的缺点可以被最小化。

第一个场景的例子:

    <GridLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:columnCount="2"
        android:useDefaultMargins="true">

        <View
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_rowWeight="1"
            android:layout_columnSpan="1"
            android:layout_columnWeight="1"
            android:layout_gravity="fill"
            android:layout_marginHorizontal="8dp"
            android:layout_marginVertical="8dp"
            android:background="@color/black" />

        <View
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_rowWeight="1"
            android:layout_columnSpan="1"
            android:layout_columnWeight="1"
            android:layout_gravity="fill"

            android:layout_marginHorizontal="8dp"
            android:layout_marginVertical="8dp"
            android:background="@color/black" />

        <View
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_rowWeight="1"
            android:layout_columnSpan="2"
            android:layout_columnWeight="1"
            android:layout_gravity="fill"

            android:layout_marginHorizontal="8dp"
            android:layout_marginVertical="8dp"
            android:background="@color/black" />

        <View
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_rowWeight="1"
            android:layout_columnSpan="1"
            android:layout_columnWeight="1"
            android:layout_gravity="fill"
            android:layout_marginHorizontal="8dp"
            android:layout_marginVertical="8dp"
            android:background="@color/black" />

        <View
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_rowWeight="1"
            android:layout_columnSpan="1"
            android:layout_columnWeight="1"
            android:layout_gravity="fill"

            android:layout_marginHorizontal="8dp"
            android:layout_marginVertical="8dp"
            android:background="@color/black" />

        <View
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_rowWeight="1"
            android:layout_columnSpan="2"
            android:layout_columnWeight="1"
            android:layout_gravity="fill"

            android:layout_marginHorizontal="8dp"
            android:layout_marginVertical="8dp"
            android:background="@color/black" />

     
        <!--        
        add more elements here with same attributes and they will fit on their own!
        -->

    </GridLayout>

输出:

第二个场景:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:ignore="HardcodedText"
    >

    <GridLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:columnCount="2"
        android:orientation="horizontal"
        android:useDefaultMargins="true"
        >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_columnSpan="1"
            android:text="this is a text"
            android:textColor="@color/white"
            android:layout_gravity="center"
            android:layout_margin="8dp"
            android:background="@color/black"
            />
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnSpan="1"
            android:layout_gravity="fill_horizontal"
            android:text="this is something cool. this should be taking more space but it is also controlling the total height of row"
            android:textColor="@color/white"
            android:gravity="center"
            android:layout_margin="8dp"
            android:background="@color/black"
            />
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnSpan="1"
            android:layout_gravity="fill_horizontal"
            android:text="once the width is determined by any child, the whole column shall take the same height"
            android:textColor="@color/white"
            android:gravity="center"
            android:layout_margin="8dp"
            android:background="@color/black"
            />
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnSpan="1"
            android:layout_gravity="fill"
            android:text="this column can only control how they shall look by layout gravity. this should look like column 0,0 but its  taking full row height/width"
            android:textColor="@color/white"
            android:gravity="center"
            android:layout_margin="8dp"
            android:background="@color/black"
            />

        <!--

        -->



    </GridLayout>

</FrameLayout>

outpus:

       <GridLayout
        android:layout_width="match_parent"
        android:layout_weight="3"
        android:columnCount="2"
        android:padding="10dp"
        android:rowCount="3"
        android:background="@drawable/background_down"
        android:layout_height="0dp">


        <androidx.cardview.widget.CardView
            android:layout_height="0dp"
            android:layout_width="0dp"
            android:layout_columnWeight="1"
            android:layout_rowWeight="1"
            android:layout_margin="10dp"
            android:elevation="10dp"
            app:cardCornerRadius="15dp"
            >
            <LinearLayout
                android:weightSum="3"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
                >

                <ImageView
                    android:layout_weight="2"
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:layout_margin="15dp"
                    android:src="@drawable/user" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Users"
                    android:textSize="16sp"
                    android:layout_marginStart="15dp"
                    android:layout_marginLeft="15dp" />
            </LinearLayout>

        </androidx.cardview.widget.CardView>
        <androidx.cardview.widget.CardView
            android:layout_height="0dp"
            android:layout_width="0dp"
            android:layout_columnWeight="1"
            android:layout_rowWeight="1"
            android:layout_margin="10dp"
            android:elevation="10dp"
            app:cardCornerRadius="15dp"
            >
            <LinearLayout
                android:weightSum="3"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
                >

                <ImageView
                    android:layout_weight="2"
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:layout_margin="15dp"
                    android:src="@drawable/addusers" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Add Users"
                    android:textSize="16sp"
                    android:layout_marginStart="15dp"
                    android:layout_marginLeft="15dp" />
            </LinearLayout>


        </androidx.cardview.widget.CardView>

        <androidx.cardview.widget.CardView
            android:layout_height="0dp"
            android:layout_width="0dp"
            android:layout_columnWeight="1"
            android:layout_rowWeight="1"
            android:layout_margin="10dp"
            android:elevation="10dp"
            app:cardCornerRadius="15dp"
            >
            <LinearLayout
                android:weightSum="3"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
                >

                <ImageView
                    android:layout_weight="2"
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:layout_margin="15dp"
                    android:src="@drawable/newspaper" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Report"
                    android:textSize="16sp"
                    android:layout_marginStart="15dp"
                    android:layout_marginLeft="15dp" />
            </LinearLayout>



        </androidx.cardview.widget.CardView>
        <androidx.cardview.widget.CardView
            android:layout_height="0dp"
            android:layout_width="0dp"
            android:layout_columnWeight="1"
            android:layout_rowWeight="1"
            android:layout_margin="10dp"
            android:elevation="10dp"
            app:cardCornerRadius="5dp"
            >
            <LinearLayout
                android:weightSum="3"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
                >

                <ImageView
                    android:layout_weight="2"
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:layout_margin="15dp"
                    android:src="@drawable/settings" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Settings"
                    android:textSize="16sp"
                    android:layout_marginStart="15dp"
                    android:layout_marginLeft="15dp" />
            </LinearLayout>


        </androidx.cardview.widget.CardView>

    </GridLayout>

你可以在这里找到完整的教程, Android Grid Layout With CardView和OnItemClickListener

Appcompat21 GridLayout有列和行权重,可以像下面这样使用,在GridLayout中均匀地创建每个网格项,如上图所示。

<android.support.v7.widget.GridLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:grid="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerHorizontal="true"
    grid:alignmentMode="alignBounds"
    grid:columnCount="4" >

    <Button android:layout_width="0dp"
        style="?buttonStyle"
        android:layout_height="0dp"
        android:text="-1"
        grid:layout_columnWeight="1"
        grid:layout_rowWeight="1"
        grid:layout_gravity="fill" />
    ...
</<android.support.v7.widget.GridLayout>

从没有v7支持库的API 21开始使用ScrollView:

XML:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    >

    <GridLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:columnCount="2"
            >

        <TextView
            android:layout_width="0dp"
            android:layout_height="100dp"
            android:layout_columnWeight="1"
            android:gravity="center"
            android:layout_gravity="fill_horizontal"
            android:background="@color/colorAccent"
            android:text="Tile1" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="100dp"
            android:layout_columnWeight="1"
            android:gravity="center"
            android:layout_gravity="fill_horizontal"
            android:background="@color/colorPrimaryDark"
            android:text="Tile2" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="100dp"
            android:layout_columnWeight="1"
            android:gravity="center"
            android:layout_gravity="fill_horizontal"
            android:background="@color/colorPrimary"
            android:text="Tile3" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="100dp"
            android:layout_columnWeight="1"
            android:gravity="center"
            android:layout_gravity="fill_horizontal"
            android:background="@color/colorAccent"
            android:text="Tile4" />

    </GridLayout>
</ScrollView>