126

The Android Developers Blog post introducing GridLayout shows this diagram of how spans impact automatic index allocation:

automatic index allocation

I am attempting to actually implement that using a GridLayout. Here is what I have so far:

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

I had to introduce the <Space> elements to ensure each column had a minimum width, otherwise, I would have a bunch of zero-width columns.

However, even with them, I get this:

sample GridLayout

Notably:

  • Despite android:layout_gravity="fill_horizontal", my widgets with column spans do not fill the spanned columns

  • Despite the android:layout_rowSpan values, nothing spans rows

Can anyone reproduce the diagram from the blog post using a GridLayout?

Thanks!

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491

5 Answers5

81

It feels pretty hacky, but I managed to get the correct look by adding an extra column and row beyond what is needed. Then I filled the extra column with a Space in each row defining a height and filled the extra row with a Space in each col defining a width. For extra flexibility, I imagine these Space sizes could be set in code to provide something similar to weights. I tried to add a screenshot, but I do not have the reputation necessary.

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

screenshot

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
kturney
  • 1,337
  • 11
  • 6
  • 7
    Well, IMHO that's incrementally less hacky than the other solution presented to date -- at least here, the hard-wired sizes are in the `Space` elements. I added a screenshot for future readers. Thanks! – CommonsWare Aug 09 '12 at 23:37
  • Why is the `rowCount` set to 8? We need 4 rows (the size of the largest `rowSpan`) plus the extra one for `Space` so that should be 5. What am I missing? – curioustechizen Aug 10 '12 at 04:19
  • I just went with the row and column counts from the picture in the original question (which is itself from an Android dev blog post). I then added 1 to the row and column counts to make room for the outside border Spaces. It should work fine with just 5 rows as well. – kturney Aug 10 '12 at 14:20
  • 5
    I find that this solution only works with `` as opposed to `` – Didia Jul 16 '13 at 21:09
  • How can i set dynamically row_span and column span...it will work? –  Jan 04 '16 at 12:27
  • look at--http://stackoverflow.com/questions/34390298/how-to-show-image-in-table-row-based-on-size –  Jan 04 '16 at 12:28
  • Why do we have orientation set to "Horizontal" inside the gridLayout if this last has child views vertically and horizontally? – Red M Nov 17 '16 at 03:21
16
<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
  • 8,131
  • 4
  • 31
  • 50
  • 2
    Thanks! What's interesting is that if I switch to the `GridLayout` from the Android Support package, the layout breaks, suggesting that the two are not completely compatible. Also, I am really hoping that there's a way to do this that does not involve hard-wiring sizes of the widgets. I'll let this roll for a bit, to see what other answers come in (if any), but I'll accept yours if nothing better shows up. Thanks again! – CommonsWare Aug 08 '12 at 23:01
  • 4
    "if I switch to the GridLayout from the Android Support package, the layout breaks" -- actually, that was my fault, not converting the required `android:` attributes to `app:` ones, using the backport's XML namespace. It does work with the backport. – CommonsWare Aug 08 '12 at 23:44
  • I found a way to have some of them dynamically size but its only if the full width of the columns or rows are already defined by adjacent views. I don't think that they work like weights do and distribute the space equally depending on the spans defined. Its not perfect but it works perfectly for what I need in my current project. – HandlerExploit Aug 09 '12 at 02:58
  • Well, your example is more like an AbsoluteLayout's aproach mixed with one for a RelativeLayout, isn't it? This is neither dynamic nor portable. Why exactly do you need a GridLayout for this? Anyways, GridLayout is, imho, either broken or unfinished... – Bondax Mar 21 '13 at 09:31
  • @Bondax This implementation clearly defines the grid item in both height, width, column width, and column span. The grid layout will float your grid items within the confined space when different widths are defined to the grid (screen width). This was a requirement for a project and this solved the issue perfectly. – HandlerExploit Mar 21 '13 at 17:34
  • @Bondax And if you don't understand, this was supposed to be an oversimplified example because that was what the question asked for, nothing more nothing less. – HandlerExploit Mar 21 '13 at 17:36
  • all of the above is possible with relativelayout Right ?!! – Lalith B Aug 22 '13 at 05:36
  • look at--http://stackoverflow.com/questions/34390298/how-to-show-image-in-table-row-based-on-size –  Jan 04 '16 at 12:29
6

You have to set both layout_gravity and layout_columntWeight on your columns

<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
  • 1,692
  • 18
  • 32
2

Android Support V7 GridLayout library makes excess space distribution easy by accommodating the principle of weight. To make a column stretch, make sure the components inside it define a weight or a gravity. To prevent a column from stretching, ensure that one of the components in the column does not define a weight or a gravity. Remember to add dependency for this library. Add com.android.support:gridlayout-v7:25.0.1 in 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
  • 5,503
  • 1
  • 16
  • 21
1

Starting from API 21, the GridLayout now supports the weight like LinearLayout. For details please see the link below:

https://stackoverflow.com/a/31089200/1296944

Community
  • 1
  • 1
Jack
  • 2,600
  • 23
  • 29