GridLayout / Layouts

GridLayout – Revisited

Back in November 2011 I posted a two part series to Styling Android which covered GridLayout which was introduced in Ice Cream Sandwich (API 14). In those articles, I have mentioned that there were hints from Google’s Dianne Hackbourn that it would be released as a compatibility library project, and it has been. However, there are some tweaks required to get it working with the code from the previous articles, so in this article we’ll look at how to convert the code from the earlier articles to use the compatibility library implementation of GridLayout.

The first thing we’ll do is check out the existing source. Once checked out, we’ll rename the project to to GridLayout-App as we’ll need to keep the project name gridlayout clear for the compatibility library project.

Next we’ll import the compatibility library for GridLayout. With the new Gradle build system we can import the library as an AAR by installing the Support Library Repository from SDK Manager, and then adding a dependency of “compile com.android.support:gridlayout-v7:13.0.0” to the dependencies section of build.gradle.

However, if you are still using the old Eclipse based build, you’ll need to First open Android SDK Manager from Window|Android SDK Manager in Eclipse, or from tools/android in your Android SDK installation, and ensure that you have the Android Support Library installed.

The compatibility / support library versioning can be a little confusing. The various editions have a version which represents the API version they are compatible to. For example, the most commonly used compatibility library is v4 which provides support for Fragments etc. back to API 4 (Donut 1.6). This library is currently, at the time of writing, at revision 11. It is this revision number which is incremented for each new release of the v4 compatibility library.

However, there are other compatibility libraries and GridLayout support is in one of these. When you have the Android Support Library installed, this can be found under extras/android/support/v7 in your Android SDK installation, and is referred to as either the v7 or GridLayout compatibility library. This is a little different from the v4 library. Whereas the v4 library only contains Java code and can be added to your project as a JAR, the v7 library also contains resources, so needs to be added as an Android Library project.

To do this, we must first create a project for the v7 library in Eclipse. First select File|Install|Android|Existing Android Code into Workspace. Then click on Browse… next to Root Directory, navigate to extras/android/support/v7 in your Android SDK installation and select Open. You should see a project named gridlayout appear in the Projects list. Click Finish and the project should be imported. Please note, if you did not rename the Styling Android project from GridLayout you will get an error here.

Next we need to import this as a library project by right clicking on our GridLayout-app project and selecting Properties|Android, then add a new library and select gridlayout. If you are importing the V7 Support library as an AAR using Gradle, just adding the dependency to gradle.build will get you to this point. The next thing that we’ll do it completely break the code in the old project by changing the minSdk and targetSdk versions in the Android Manifest to 7. If you now make some minor edits to the layouts in main.xml and both.xml you will see errors appear because GridLayout is not supported in API 7.

So, all we need to do now is fix these errors!. The first thing that we need to do is change the XML to use android.support.v7.widget.GridLayout instead of the existing GridLayout. For example, both.xml changes to:

This clears the errors so, on the face of it should work. However, if we run this we can clearly see that GridLayout version is not rendering the same as the LinearLayout version:

What’s going wrong here? The problem is the result of the way in which the attributes specific to GridLayout are being specified. GridLayout is now being included as an Android Library project, meaning that it falls in to the namespace of our app, rather than being in the android namespace as it was when we were using the implementation baked in to the OS. To fix this we need to change any of the attributes specific to GridLayout (which are defined in res/values/attrs.xml within the gridlayout project).

The first thing we need to do is declare our namespace. We’ll create a Styling Android namespace (sa):

res-auto will always resolve to the package name of the current project.

Then we need to change the specific attributes of the GridLayout and its children to use this namespace:

If we now try this, the GridLayout behaviour matches the LinearLayout behaviour as it did before we started tinkering with things:

It can be a little confusing at first to work out which attributes need to be in the android namespace, and which need to be in our sa namespace. The easy way to remember it is that any attributes of the GridLayout itself that are additions to the parameters of ViewGroup (which GridLayout extends) should be in the sa namespace, and all attributes of ViewGroup and its ancestors are in the android namespace. For the children of the GridLayout, all layout_* attributes are in the sa namespace, and all others are in their usual namespace.

That concludes our look back on GridLayout. While there are a couple of things to watch out for, it’s actually pretty easy to get it working, so there’s no excuse for using it for projects targeting SDK 7 and higher (which according to the Android developer dashboard, at the time of writing, will cover 99.6% of all Android users).

The source code for this article can be found here.

© 2013, Mark Allison. All rights reserved.

CC BY-NC-SA 4.0 GridLayout – Revisited by Styling Android is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Permissions beyond the scope of this license may be available at http://blog.stylingandroid.com/license-information.

1 Comment

Leave a Reply

Your email address will not be published. Required fields are marked *