GridLayout e Row / Column Span Woe

121

A publicação do Blog do desenvolvedor AndroidGridLayout mostra este diagrama de como os spans afetam a alocação automática de índice:

alocação automática de índice

Eu estou tentando realmente implementar isso usando um GridLayout. Aqui está o que eu tenho até agora:

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

Eu tive que apresentar os <Space>elementos para garantir que cada coluna tivesse uma largura mínima; caso contrário, eu teria um monte de colunas de largura zero.

No entanto, mesmo com eles, recebo o seguinte:

amostra GridLayout

Notavelmente:

  • Apesar disso android:layout_gravity="fill_horizontal", meus widgets com extensão de coluna não preenchem as colunas estendidas

  • Apesar dos android:layout_rowSpanvalores, nada abrange linhas

Alguém pode reproduzir o diagrama da postagem do blog usando a GridLayout?

Obrigado!

CommonsWare
fonte
178
Eu acho que mesmo você faz perguntas :)
StackOverflowed

Respostas:

76

Parece bastante hacky, mas consegui obter a aparência correta adicionando uma coluna e linha extra além do necessário. Em seguida, preenchi a coluna extra com um espaço em cada linha, definindo uma altura e preenchi a linha extra com um espaço em cada coluna, definindo uma largura. Para maior flexibilidade, imagino que esses tamanhos de espaço possam ser definidos no código para fornecer algo semelhante aos pesos. Tentei adicionar uma captura de tela, mas não tenho a reputação necessária.

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

kturney
fonte
7
Bem, o IMHO é cada vez menos hacky do que a outra solução apresentada até o momento - pelo menos aqui, os tamanhos com fio estão nos Spaceelementos. Eu adicionei uma captura de tela para futuros leitores. Obrigado!
CommonsWare
Por que o rowCountconjunto está definido como 8? Precisamos de 4 linhas (o tamanho da maior rowSpan) e a mais uma para Spaceque seja 5. O que estou perdendo?
precisa saber é o seguinte
Eu apenas fui com as contagens de linha e coluna da imagem na pergunta original (que é ela própria de uma postagem de blog de desenvolvedor do Android). Em seguida, adicionei 1 à contagem de linhas e colunas para liberar espaço para os Espaços da borda externa. Deve funcionar bem com apenas 5 linhas também.
kturney
5
Eu acho que esta solução só funciona <Gridlayout>em oposição a<android.support.v7.widget.GridLayout>
Didia 16/07/2013
Como definir dinamicamente row_span e extensão da coluna ... 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>

ScreenShot

HandlerExploit
fonte
2
Obrigado! O interessante é que, se eu mudar para o GridLayoutpacote de suporte do Android, o layout será interrompido, sugerindo que os dois não são completamente compatíveis. Além disso, espero realmente que haja uma maneira de fazer isso que não envolva os tamanhos de conexão dos widgets. Vou deixar isso rolar um pouco, para ver que outras respostas chegam (se houver), mas aceito as suas se nada melhor aparecer. Obrigado novamente!
CommonsWare 8/08/12
4
"se eu mudar para o GridLayout no pacote de suporte do Android, o layout será interrompido" - na verdade, foi minha culpa, não convertendo os android:atributos necessários em um app:, usando o espaço de nome XML do backport. Funciona com o backport.
CommonsWare 8/08/12
Eu encontrei uma maneira de ter alguns deles de tamanho dinâmico, mas é apenas se a largura total das colunas ou linhas já estiver definida por visualizações adjacentes. Não acho que eles funcionem como pesos e distribuem o espaço igualmente, dependendo dos intervalos definidos. Não é perfeito, mas funciona perfeitamente para o que eu preciso no meu projeto atual.
precisa saber é o seguinte
Bem, seu exemplo é mais como a abordagem de um AbsoluteLayout misturada com a de um RelativeLayout, não é? Isso não é dinâmico nem portátil. Por que exatamente você precisa de um GridLayout para isso? De qualquer forma, GridLayout é, IMHO, seja quebrado ou inacabada ...
Bondax
@Bondax Esta implementação define claramente o item da grade em altura, largura, largura da coluna e extensão da coluna. O layout da grade irá flutuar os itens da grade dentro do espaço confinado quando diferentes larguras são definidas para a grade (largura da tela). Este era um requisito para um projeto e resolveu o problema perfeitamente.
precisa saber é o seguinte
6

Você precisa definir layout_gravity e layout_columntWeight em suas colunas

<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
fonte
2

A biblioteca GridLayout do Suporte Android V7 facilita a distribuição excessiva de espaço, acomodando o princípio do peso. Para esticar uma coluna, verifique se os componentes dentro dela definem um peso ou uma gravidade. Para impedir que uma coluna se estique, verifique se um dos componentes da coluna não define um peso ou uma gravidade. Lembre-se de adicionar dependência para esta biblioteca. Adicione com.android.support:gridlayout-v7:25.0.1 em 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
fonte