GridLayout y problemas de tramo de filas / columnas

121

La publicación del blog de desarrolladores de Android que presentaGridLayout este diagrama muestra cómo los intervalos afectan la asignación automática de índices:

asignación automática de índices

Estoy intentando implementar eso usando un GridLayout. Esto es lo que tengo hasta ahora:

<android.support.v7.widget.GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res/com.commonsware.android.gridlayout"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    app:orientation="horizontal"
    app:columnCount="8">

    <Button
        app:layout_columnSpan="2"
        app:layout_rowSpan="2"
        android:layout_gravity="fill_horizontal"
        android:text="@string/string_1"/>

  <Button
    app:layout_columnSpan="2"
    android:layout_gravity="fill_horizontal"
    android:text="@string/string_2"/>

  <Button
    app:layout_rowSpan="4"
    android:text="@string/string_3"/>

  <Button
    app:layout_columnSpan="3"
    app:layout_rowSpan="2"
    android:layout_gravity="fill_horizontal"
    android:text="@string/string_4"/>

  <Button
    app:layout_columnSpan="3"
    android:layout_gravity="fill_horizontal"
    android:text="@string/string_5"/>

  <Button
    app:layout_columnSpan="2"
    android:layout_gravity="fill_horizontal"
    android:text="@string/string_6"/>

  <android.support.v7.widget.Space
    app:layout_column="0"
    android:layout_width="36dp"
    />

  <android.support.v7.widget.Space
    android:layout_width="36dp"
    />

  <android.support.v7.widget.Space
    android:layout_width="36dp"
    />

  <android.support.v7.widget.Space
    android:layout_width="36dp"
    />

  <android.support.v7.widget.Space
    android:layout_width="36dp"
    />

  <android.support.v7.widget.Space
    android:layout_width="36dp"
    />

  <android.support.v7.widget.Space
    android:layout_width="36dp"
    />

  <android.support.v7.widget.Space
    android:layout_width="36dp"
    />

</android.support.v7.widget.GridLayout>

Tuve que introducir los <Space>elementos para asegurarme de que cada columna tuviera un ancho mínimo, de lo contrario, tendría un montón de columnas de ancho cero.

Sin embargo, incluso con ellos, obtengo esto:

muestra GridLayout

Notablemente:

  • Sin embargo android:layout_gravity="fill_horizontal", mis widgets con tramos de columna no llenan las columnas distribuidas

  • A pesar de los android:layout_rowSpanvalores, nada abarca filas.

¿Alguien puede reproducir el diagrama de la publicación del blog usando un GridLayout?

¡Gracias!

CommonsWare
fuente
178
Supongo que incluso hacer preguntas :)
StackOverflowed

Respuestas:

76

Se siente bastante extraño, pero logré obtener el aspecto correcto agregando una columna y una fila adicionales más allá de lo necesario. Luego llené la columna adicional con un espacio en cada fila que define una altura y llené la fila adicional con un espacio en cada columna que define un ancho. Para mayor flexibilidad, imagino que estos tamaños de espacio podrían configurarse en código para proporcionar algo similar a los pesos. Intenté agregar una captura de pantalla, pero no tengo la reputación necesaria.

<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:columnCount="9"
android:orientation="horizontal"
android:rowCount="8" >

<Button
    android:layout_columnSpan="2"
    android:layout_gravity="fill"
    android:layout_rowSpan="2"
    android:text="1" />

<Button
    android:layout_columnSpan="2"
    android:layout_gravity="fill_horizontal"
    android:text="2" />

<Button
    android:layout_gravity="fill_vertical"
    android:layout_rowSpan="4"
    android:text="3" />

<Button
    android:layout_columnSpan="3"
    android:layout_gravity="fill"
    android:layout_rowSpan="2"
    android:text="4" />

<Button
    android:layout_columnSpan="3"
    android:layout_gravity="fill_horizontal"
    android:text="5" />

<Button
    android:layout_columnSpan="2"
    android:layout_gravity="fill_horizontal"
    android:text="6" />

<Space
    android:layout_width="36dp"
    android:layout_column="0"
    android:layout_row="7" />

<Space
    android:layout_width="36dp"
    android:layout_column="1"
    android:layout_row="7" />

<Space
    android:layout_width="36dp"
    android:layout_column="2"
    android:layout_row="7" />

<Space
    android:layout_width="36dp"
    android:layout_column="3"
    android:layout_row="7" />

<Space
    android:layout_width="36dp"
    android:layout_column="4"
    android:layout_row="7" />

<Space
    android:layout_width="36dp"
    android:layout_column="5"
    android:layout_row="7" />

<Space
    android:layout_width="36dp"
    android:layout_column="6"
    android:layout_row="7" />

<Space
    android:layout_width="36dp"
    android:layout_column="7"
    android:layout_row="7" />

<Space
    android:layout_height="36dp"
    android:layout_column="8"
    android:layout_row="0" />

<Space
    android:layout_height="36dp"
    android:layout_column="8"
    android:layout_row="1" />

<Space
    android:layout_height="36dp"
    android:layout_column="8"
    android:layout_row="2" />

<Space
    android:layout_height="36dp"
    android:layout_column="8"
    android:layout_row="3" />

<Space
    android:layout_height="36dp"
    android:layout_column="8"
    android:layout_row="4" />

<Space
    android:layout_height="36dp"
    android:layout_column="8"
    android:layout_row="5" />

<Space
    android:layout_height="36dp"
    android:layout_column="8"
    android:layout_row="6" />

</GridLayout>

captura de pantalla

kturney
fuente
7
Bueno, en mi humilde opinión, eso es incrementalmente menos hacky que la otra solución presentada hasta la fecha; al menos aquí, los tamaños cableados están en los Spaceelementos. Agregué una captura de pantalla para futuros lectores. ¡Gracias!
CommonsWare
¿Por qué se rowCountestablece en 8? Necesitamos 4 filas (el tamaño de la más grande rowSpan) más una adicional para Spaceque sea 5. ¿Qué me falta?
curioso técnico
Simplemente seguí los recuentos de filas y columnas de la imagen en la pregunta original (que es en sí misma de una publicación de blog de desarrollo de Android). Luego agregué 1 a los recuentos de filas y columnas para dejar espacio para los espacios del borde exterior. También debería funcionar bien con solo 5 filas.
kturney
5
Encuentro que esta solución solo funciona <Gridlayout>en lugar de<android.support.v7.widget.GridLayout>
Didia
¿Cómo puedo establecer dinámicamente row_span y column span ... funcionará?
17
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <GridLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:columnCount="8"
        android:rowCount="7" >

        <TextView
            android:layout_width="50dip"
            android:layout_height="50dip"
            android:layout_columnSpan="2"
            android:layout_rowSpan="2"
            android:background="#a30000"
            android:gravity="center"
            android:text="1"
            android:textColor="@android:color/white"
            android:textSize="20dip" />

        <TextView
            android:layout_width="50dip"
            android:layout_height="25dip"
            android:layout_columnSpan="2"
            android:layout_rowSpan="1"
            android:background="#0c00a3"
            android:gravity="center"
            android:text="2"
            android:textColor="@android:color/white"
            android:textSize="20dip" />

        <TextView
            android:layout_width="25dip"
            android:layout_height="100dip"
            android:layout_columnSpan="1"
            android:layout_rowSpan="4"
            android:background="#00a313"
            android:gravity="center"
            android:text="3"
            android:textColor="@android:color/white"
            android:textSize="20dip" />

        <TextView
            android:layout_width="75dip"
            android:layout_height="50dip"
            android:layout_columnSpan="3"
            android:layout_rowSpan="2"
            android:background="#a29100"
            android:gravity="center"
            android:text="4"
            android:textColor="@android:color/white"
            android:textSize="20dip" />

        <TextView
            android:layout_width="75dip"
            android:layout_height="25dip"
            android:layout_columnSpan="3"
            android:layout_rowSpan="1"
            android:background="#a500ab"
            android:gravity="center"
            android:text="5"
            android:textColor="@android:color/white"
            android:textSize="20dip" />

        <TextView
            android:layout_width="50dip"
            android:layout_height="25dip"
            android:layout_columnSpan="2"
            android:layout_rowSpan="1"
            android:background="#00a9ab"
            android:gravity="center"
            android:text="6"
            android:textColor="@android:color/white"
            android:textSize="20dip" />
    </GridLayout>

</RelativeLayout>

Captura de pantalla

HandlerExploit
fuente
2
¡Gracias! Lo interesante es que si cambio al GridLayoutpaquete de soporte de Android, el diseño se rompe, lo que sugiere que los dos no son completamente compatibles. Además, realmente espero que haya una manera de hacer esto que no implique tamaños de cableado de los widgets. Dejaré que esto pase un poco, para ver qué otras respuestas vienen (si las hay), pero aceptaré la tuya si no aparece nada mejor. ¡Gracias de nuevo!
CommonsWare
4
"si cambio a GridLayout desde el paquete de soporte de Android, el diseño se rompe"; en realidad, fue mi culpa, no convertir los android:atributos requeridos en app:unos, usando el espacio de nombres XML del backport. Funciona con el backport.
CommonsWare
Encontré una manera de tener algunos de ellos de tamaño dinámico, pero es solo si el ancho completo de las columnas o filas ya está definido por vistas adyacentes. No creo que funcionen como lo hacen los pesos y distribuyan el espacio por igual dependiendo de los tramos definidos. No es perfecto, pero funciona perfectamente para lo que necesito en mi proyecto actual.
HandlerExploit
Bueno, su ejemplo se parece más al enfoque de AbsoluteLayout mezclado con uno de RelativeLayout, ¿no es así? Esto no es dinámico ni portátil. ¿Por qué exactamente necesitas un GridLayout para esto? De todos modos, GridLayout está, en mi humilde opinión, roto o sin terminar ...
Bondax
@Bondax Esta implementación define claramente el elemento de la cuadrícula en altura, ancho, ancho de columna y extensión de columna. El diseño de la cuadrícula hará flotar los elementos de la cuadrícula dentro del espacio confinado cuando se definen diferentes anchos en la cuadrícula (ancho de pantalla). Este era un requisito para un proyecto y esto resolvió el problema perfectamente.
HandlerExploit
6

Debe establecer tanto layout_gravity como layout_columntWeight en sus columnas

<android.support.v7.widget.GridLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView android:text="سوم شخص"
        app:layout_gravity="fill_horizontal"
        app:layout_columnWeight="1"
        />

    <TextView android:text="دوم شخص"
        app:layout_gravity="fill_horizontal"
        app:layout_columnWeight="1"
        />

    <TextView android:text="اول شخص"
        app:layout_gravity="fill_horizontal"
        app:layout_columnWeight="1"
        />
 </android.support.v7.widget.GridLayout>
Hossein Shahdoost
fuente
2

La biblioteca GridLayout de Android Support V7 facilita la distribución del espacio sobrante al adaptarse al principio del peso. Para hacer que una columna se estire, asegúrese de que los componentes dentro de ella definan un peso o una gravedad. Para evitar que una columna se estire, asegúrese de que uno de los componentes de la columna no defina un peso o una gravedad. Recuerde agregar dependencia para esta biblioteca. Agregue com.android.support:gridlayout-v7:25.0.1 en build.gradle.

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:columnCount="2"
app:rowCount="2">

<TextView
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:gravity="center"
    android:text="First"
    app:layout_columnWeight="1"
    app:layout_rowWeight="1" />

<TextView
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:gravity="center"
    android:text="Second"
    app:layout_columnWeight="1"
    app:layout_rowWeight="1" />

<TextView
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:gravity="center"
    android:text="Third"
    app:layout_columnWeight="1"
    app:layout_rowWeight="1" />

<TextView
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:gravity="center"        
    app:layout_columnWeight="1"
    app:layout_rowWeight="1"
    android:text="fourth"/>

</android.support.v7.widget.GridLayout>
Permita
fuente