studio recyclerview how gridlayout example cardview android android-layout android-gridview android-gridlayout

android - recyclerview - GridLayout(no GridView) cómo estirar a todos los niños de manera uniforme



how to use gridview (16)

Quiero tener una cuadrícula de 2x2 con botones dentro. Esto es solo ICS, así que estoy tratando de usar el nuevo GridLayout dado.

Aquí está el XML de mi diseño:

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

El problema es que mis puntos de vista no se extienden de manera uniforme para cada fila. Esto causa mucho espacio extra a la derecha de mi GridLayout.

Intenté establecer layout_gravity="fill_horizontal" pero eso solo se aplica a la última vista en la fila. Esto significa que la Celda 1 se extiende hasta el final para dar suficiente espacio para la Celda 0.

¿Pensamientos sobre cómo abordar esto?


Aquí estás :

Button button = new Button(this); // weight = 1f , gravity = GridLayout.FILL GridLayout.LayoutParams param= new GridLayout.LayoutParams(GridLayout.spec( GridLayout.UNDEFINED,GridLayout.FILL,1f), GridLayout.spec(GridLayout.UNDEFINED,GridLayout.FILL,1f)); // Layout_height = 0 ,Layout_weight = 0 params.height =0; params.width = 0; button.setLayoutParams(param);


Comenzando en API 21 sin la biblioteca de soporte v7 con 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>


Comenzando en API 21, la noción de peso se agregó a GridLayout. Para admitir dispositivos Android antiguos, puede usar GridLayout desde la biblioteca de soporte v7.

El siguiente XML proporciona un ejemplo de cómo puede usar pesos para llenar el ancho de la pantalla.

<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.GridLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:grid="http://schemas.android.com/apk/res-auto" android:id="@+id/choice_grid" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:padding="4dp" grid:alignmentMode="alignBounds" grid:columnCount="2" grid:rowOrderPreserved="false" grid:useDefaultMargins="true"> <TextView android:layout_width="0dp" android:layout_height="100dp" grid:layout_columnWeight="1" grid:layout_gravity="fill_horizontal" android:gravity="center" android:background="#FF33B5E5" android:text="Tile1" /> <TextView android:layout_width="0dp" android:layout_height="100dp" grid:layout_columnWeight="1" grid:layout_gravity="fill_horizontal" android:gravity="center" android:background="#FF33B5E5" android:text="Tile2" /> <TextView android:layout_width="0dp" android:layout_height="100dp" grid:layout_columnWeight="1" grid:layout_gravity="fill_horizontal" android:gravity="center" android:background="#FF33B5E5" android:text="Tile3" /> <TextView android:layout_width="0dp" android:layout_height="100dp" grid:layout_columnWeight="1" grid:layout_gravity="fill_horizontal" android:gravity="center" android:background="#FF33B5E5" android:text="Tile4" /> </android.support.v7.widget.GridLayout>


En mi caso, estaba agregando los botones dinámicamente, por lo que mi solución requería parte de XML y parte de Java. Tuve que encontrar y mezclar soluciones de algunos lugares diferentes y pensé que lo compartiría aquí para que alguien más que buscara la solución similar lo encontrara útil.

Primera parte de mi archivo de diseño XML ...

<android.support.v7.widget.GridLayout xmlns:grid="http://schemas.android.com/apk/res-auto" android:id="@+id/gl_Options" android:layout_width="match_parent" android:layout_height="wrap_content" grid:useDefaultMargins="true"> </android.support.v7.widget.GridLayout>

grid:useDefaultMargins="true" no es necesario pero agregué porque me pareció mejor, puede aplicar otros efectos visuales (por ejemplo, relleno) como se menciona en algunas respuestas aquí. Ahora para los botones, ya que tengo que agregarlos dinámicamente. Aquí está la parte de Java de mi código para hacer estos botones, estoy incluyendo solo aquellas líneas relacionadas con este contexto. Supongamos que tengo que crear botones de tantas myOptions disponibles para mi código y no estoy copiando el código de OnClickListener también.

import android.support.v7.widget.GridLayout; //Reference to Library public class myFragment extends Fragment{ GridLayout gl_Options; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { gl_AmountOptions = (GridLayout)view.findViewById( R.id.gl_AmountOptions ); ... gl_Options.removeAllViews(); // Remove all existing views gl_AmountOptions.setColumnCount( myOptions.length <= 9 ? 3: 4 ); // Set appropriate number of columns for( String opt : myOptions ) { GridLayout.LayoutParams lParams = new GridLayout.LayoutParams( GridLayout.spec( GridLayout.UNDEFINED, 1f), GridLayout.spec( GridLayout.UNDEFINED, 1f)); // The above defines LayoutParameters as not specified Column and Row with grid:layout_columnWeight="1" and grid:layout_rowWeight="1" lParams.width = 0; // Setting width to "0dp" so weight is applied instead Button b = new Button(this.getContext()); b.setText( opt ); b.setLayoutParams(lParams); b.setOnClickListener( myClickListener ); gl_Options.addView( b ); } } }

Como estamos usando GridLayout desde la biblioteca de soporte y no con el GridLayout estándar, tenemos que decirlo en el archivo YourProject.grade .

dependencies { compile ''com.android.support:appcompat-v7:23.4.0'' ... compile ''com.android.support:gridlayout-v7:23.4.0'' }


Esta es la respuesta correcta

<?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:layout_columnWeight="1" android:layout_rowWeight="1" android:textSize="14dip" /> <Button android:text="Cell 1" android:layout_row="0" android:layout_column="1" android:textSize="14dip" android:layout_columnWeight="1" android:layout_rowWeight="1"/> <Button android:text="Cell 2" android:layout_row="1" android:layout_column="0" android:textSize="14dip" android:layout_columnWeight="1" android:layout_rowWeight="1"/> <Button android:text="Cell 3" android:layout_row="1" android:layout_column="1" android:textSize="14dip" android:layout_columnWeight="1" android:layout_rowWeight="1"/> </GridLayout>


Esta es una pregunta bastante antigua, pero evidentemente de interés para mucha gente. Para un diseño simple de 4 botones como este, parece que un TableLayout es la forma más fácil de lograr el resultado deseado.

Aquí hay un código de ejemplo que muestra las primeras 2 filas de una tabla con 6 columnas que abarcan el ancho de su matriz. LinearLayout e ImageView en cada celda se utilizan para permitir el "encendido y apagado" de una imagen dentro de la celda mientras persiste el color de la celda.

<TableLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:stretchColumns="1,2,3,4,5,6" android:background="@drawable/vertical_radio_button_background" android:padding="2dp"> <TableRow android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:id="@+id/brown" android:tag="13" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_horizontal" android:layout_margin="1dp" android:layout_column="1" android:background="@color/brown"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:src="@drawable/selected_check" android:visibility="invisible"/> </LinearLayout> <LinearLayout android:id="@+id/maraschino" android:tag="9" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_horizontal" android:layout_margin="1dp" android:layout_column="2" android:background="@color/maraschino"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:src="@drawable/selected_check" android:visibility="invisible"/> </LinearLayout> <LinearLayout android:id="@+id/cayenne" android:tag="22" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_horizontal" android:layout_margin="1dp" android:layout_column="3" android:background="@color/cayenne"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:src="@drawable/selected_check" android:visibility="invisible"/> </LinearLayout> <LinearLayout android:id="@+id/maroon" android:tag="18" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_horizontal" android:layout_margin="1dp" android:layout_column="4" android:background="@color/maroon"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:src="@drawable/selected_check" android:visibility="invisible"/> </LinearLayout> <LinearLayout android:id="@+id/plum" android:tag="3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_horizontal" android:layout_margin="1dp" android:layout_column="5" android:background="@color/plum"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:src="@drawable/selected_check" android:visibility="invisible"/> </LinearLayout> <LinearLayout android:id="@+id/eggplant" android:tag="15" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_horizontal" android:layout_margin="1dp" android:layout_column="6" android:background="@color/eggplant"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:src="@drawable/selected_check" android:visibility="invisible"/> </LinearLayout> </TableRow> <TableRow android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:id="@+id/plum2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_horizontal" android:layout_margin="1dp" android:layout_column="1" android:background="@color/plum"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:src="@drawable/selected_check" android:visibility="invisible"/> </LinearLayout> <LinearLayout android:id="@+id/lavender" android:tag="14" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_horizontal" android:layout_margin="1dp" android:layout_column="2" android:background="@color/lavender"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:src="@drawable/selected_check" android:visibility="invisible"/> </LinearLayout> <LinearLayout android:id="@+id/carnation" android:tag="16" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_horizontal" android:layout_margin="1dp" android:layout_column="3" android:background="@color/carnation"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:src="@drawable/selected_check" android:visibility="invisible"/> </LinearLayout> <LinearLayout android:id="@+id/light_pink" android:tag="23" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_horizontal" android:layout_margin="1dp" android:layout_column="4" android:background="@color/light_pink"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:src="@drawable/selected_check" android:visibility="invisible"/> </LinearLayout> <LinearLayout android:id="@+id/strawberry" android:tag="10" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_horizontal" android:layout_margin="1dp" android:layout_column="5" android:background="@color/strawberry"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:src="@drawable/selected_check" android:visibility="invisible"/> </LinearLayout> <LinearLayout android:id="@+id/magenta" android:tag="20" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_horizontal" android:layout_margin="1dp" android:layout_column="6" android:background="@color/magenta"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:src="@drawable/selected_check" android:visibility="invisible"/> </LinearLayout> </TableRow> </TableLayout>


Esto es lo que hice y estoy feliz de decir que esto funcionó para mí. Yo también quería una grilla de elementos de 2x2, 3x3 etc. para cubrir toda la pantalla. Gridlayouts no se adhieren al ancho de la pantalla. LinearLayouts tipo de trabajo pero no puedes usar pesos anidados.

La mejor opción para mí fue utilizar Fragmentos. Utilicé this tutorial para comenzar con lo que quería hacer.

Aquí hay un código:

Actividad principal:

public class GridHolderActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main_6); } }

activity_main_6 XML (infla 3 fragmentos)

<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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" android:orientation="vertical"> <fragment android:id="@+id/frag1" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:name=".TwoHorizontalGridFragment" tools:layout="@layout/two_horiz" /> <fragment android:id="@+id/frag2" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:name=".TwoHorizontalGridFragment" tools:layout="@layout/two_horiz" /> <fragment android:id="@+id/frag3" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:name=".Grid.TwoHorizontalGridFragment" tools:layout="@layout/two_horiz" />

Disposición de fragmento de base

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_gravity="center" android:layout_height="match_parent"> <ImageQueue android:layout_width="0dp" android:layout_height="wrap_content" android:id="@+id/img1" android:layout_weight="1"/> <ImageQueue android:layout_width="0dp" android:layout_height="wrap_content" android:id="@+id/img2" android:layout_weight="1"/> </LinearLayout>

Fragment Class (solo maneja la inicialización de una vista personalizada) infla 2 mosaicos por fragmento

public class TwoHorizontalGridFragment extends Fragment { private View rootView; private ImageQueue imageQueue1; private ImageQueue imageQueue2; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { /** * Inflate the layout for this fragment */ rootView = inflater.inflate( R.layout.two_horiz, container, false); return rootView; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); imageQueue1 = (ImageQueue)rootView.findViewById(R.id.img1); imageQueue2 = (ImageQueue)rootView.findViewById(R.id.img2); imageQueue1.updateFiles(); imageQueue2.updateFiles(); }

}

¡Eso es!

Este es un trabajo extraño para usar pesos anidados, esencialmente. Me da una cuadrícula perfecta de 2x3 que llena toda la pantalla de mi tableta de 10 pulgadas y mi ADN droide HTC. ¡Dejame saber como te va!


Finalmente encontré la solución. Como dijo Rotemmiz, tienes que hacerlo dinámicamente luego. Este código extiende los botones para llenar la vista horizontalmente, pero lo mismo puede hacerse verticalmente.

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

(El 20 es para el relleno interno y externo y los márgenes. Esto podría hacerse de manera más universal, pero esto es mucho más limpio)

Entonces se puede llamar así:

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

Debe hacerse con un observador porque tenemos que esperar a que se dibuje la vista antes de llamar a las vistas.


Intente agregar lo siguiente a su especificación GridLayout. Eso debería funcionar.

android:useDefaultMargins="true"


La mejor solución que pude encontrar es usar un diseño lineal (horizontal) para cada fila que desee y dentro de él asignar el ancho del botón (celda) a 0dp y el peso a 1. Para cada uno de los diseños lineales (filas), asigne la altura a 0dp y el peso a 1. Encuentre el siguiente código: también android: layout_gravity = "center_vertical" se usa para alinear los botones en una fila en caso de que contengan texto de longitud variable. El uso de 0dp y el peso es un truco bastante ordenado pero no tan conocido.

<LinearLayout android:id="@+id/parent_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/button_bue_3d" android:orientation="vertical" > <LinearLayout android:id="@+id/layout_row1" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="horizontal" > <Button android:id="@+id/button1" style="?android:attr/buttonStyleSmall" android:layout_height="wrap_content" android:layout_width="0dp" android:layout_weight="1" android:clickable="false" android:layout_gravity="center_vertical" android:text="ssssssssssssssssssssssssss" /> <Button android:id="@+id/button2" style="?android:attr/buttonStyleSmall" android:clickable="false" android:layout_height="wrap_content" android:layout_width="0dp" android:layout_weight="1" android:layout_gravity="center_vertical" android:text="sggggggg" /> </LinearLayout> <LinearLayout android:id="@+id/layout_row2" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="0dp" android:orientation="horizontal" > <Button android:id="@+id/button3" style="?android:attr/buttonStyleSmall" android:layout_height="wrap_content" android:layout_width="0dp" android:layout_weight="1" android:layout_gravity="center_vertical" android:text="s" /> <Button android:id="@+id/button4" style="?android:attr/buttonStyleSmall" android:layout_height="wrap_content" android:layout_width="0dp" android:layout_weight="1" android:clickable="false" android:layout_gravity="center_vertical" android:text="s" /> </LinearLayout> </LinearLayout>



Puede establecer el ancho de cada elemento de forma dinámica:

GridLayout.LayoutParams params = (GridLayout.LayoutParams) child.getLayoutParams(); params.width = (parent.getWidth()/parent.getColumnCount()) -params.rightMargin - params.leftMargin; child.setLayoutParams(params);


Puede hacer que esto sea mucho más rápido anulando el método ViewGroup onLayout. Esta es mi solución universal:

package your.app.package; import android.content.Context; import android.view.ViewGroup; public class GridLayout extends ViewGroup { public GridLayout(Context context) { super(context); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int columns = 2;//edit this if you need different grid final int rows = 2; int children = getChildCount(); if (children != columns * rows) throw new IllegalStateException("GridLayout must have " + columns * rows + " children"); int width = getWidth(); int height = getHeight(); int viewWidth = width / columns; int viewHeight = height / rows; int rowIndex = 0; int columnIndex = 0; for (int i = 0; i < children; i++) { getChildAt(i).layout(viewWidth * columnIndex, viewHeight * rowIndex, viewWidth * columnIndex + viewWidth, viewHeight * rowIndex + viewHeight); columnIndex++; if (columnIndex == columns) { columnIndex = 0; rowIndex++; } } } }

EDITAR: ¡No olvide match_parent para niños!

android:layout_width="match_parent" android:layout_height="match_parent"


Quería tener una mesa centrada con las etiquetas alineadas a la derecha y los valores alineados a la izquierda. El espacio extra debería estar alrededor de la mesa. Después de mucho experimentar y no seguir lo que la documentación decía que debía hacer, se me ocurrió algo que funciona. Esto es lo que hice:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:orientation="vertical" > <GridLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:columnCount="2" android:orientation="horizontal" android:useDefaultMargins="true" > <TextView android:layout_gravity="right" android:text="Short label:" /> <TextView android:id="@+id/start_time" android:layout_gravity="left" android:text="Long extended value" /> <TextView android:layout_gravity="right" android:text="A very long extended label:" /> <TextView android:id="@+id/elapsed_time" android:layout_gravity="left" android:text="Short value" /> </GridLayout>

Esto parece funcionar, pero el GridLayout muestra el mensaje:

"Este diseño de GridLayout o su padre LinearLayout es inútil"

No estoy seguro de por qué es "inútil" cuando funciona para mí.

No estoy seguro de por qué funciona esto o si es una buena idea, pero si lo prueba y puede proporcionar una mejor idea, una pequeña mejora o explicar por qué funciona (o no funcionará), agradecería los comentarios.

Gracias.


Appcompat21 GridLayout tiene los pesos de columna y fila que se pueden usar a continuación para crear uniformemente cada elemento de la cuadrícula en la cuadrícula como la imagen de arriba.

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


ACTUALIZACIÓN : los pesos son compatibles a partir de la API 21. Consulte la respuesta de PaulT para obtener más detalles. FINALIZAR ACTUALIZACIÓN Existen limitaciones al usar GridLayout, la siguiente cita se toma de la documentation .

"GridLayout no proporciona soporte para el principio de peso, tal como se define en peso. En general, no es posible configurar un GridLayout para distribuir el exceso de espacio en proporciones no triviales entre múltiples filas o columnas ... Para un control completo sobre exceso de distribución de espacio en una fila o columna, use una subvista LinearLayout para mantener los componentes en el grupo celular asociado ".

Aquí hay un pequeño ejemplo que usa subvistas de LinearLayout. (Utilicé Vistas espaciales que ocupa el área no utilizada y coloca los botones en la posición deseada).

<GridLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:columnCount="1" > <TextView android:text="2x2 button grid" android:textSize="32dip" android:layout_gravity="center_horizontal" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Space android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button 1" /> <Space android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="start" android:text="Button 2" /> <Space android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <Space android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button 3" /> <Space android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="start" android:text="Button 4" /> <Space android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" /> </LinearLayout> </GridLayout>