Our new Tech Feed article introduces a component for Android SDK created by AndriyTsykholyas, N-iX Senior Software Engineer. Andriy joined our company over 9 years ago and currently is involved in a project for global telecommunications company that provide services using the mobile virtual network operator.

Introduction

GridLayout is a great container, however it is not able to distribute excess space between rows or columns in specified proportions. Despite this, Android developers still can achieve such ability by implementing their own grid layout which is not as hard as it may sound. Below I will show a new type of container that I called WeigthedGridLayout and describe how to create it and make it work properly. For simplicity reasons I’ll create and populate the grid in code, not in XML.
Four steps to create the grid:

  1. create own LayoutParams subclass
  2. save row and column weights
  3. override onMeasure()
  4. override onLayout()

Creating own LayoutParams subclass

code

For our grid we need cell coordinates and (optionally) row and column spans.

Saving weights of columns and rows

The easiest way is to accept the weights as constructor parameters.

code

Here I also initialize arrays with column and row sizes (which will store sizes in pixels).

Overriding onMeasure()

Here I distribute column and row sizes (according to their weights) and measure children. To keep the sample short I ignore UNSPECIFIED option. Also children occupy all available space (no gravity).

code

To keep onMeasure() short and to avoid code duplication I additionally use 3 auxiliary methods. The only interesting part here is calculateChildSize() method. It uses cell size and (in case of span) spanned cell sizes.

Overriding onLayout()

This is the most interesting part. Here I calculate rectangles for each child and call layout() on them.

code

Again, to keep onLayout() short and to not duplicate the code I add 2 auxiliary methods.

Example

Now lets create a sample grid and fill it with child views. In this sample I fill only part of the cells.

code

The grid can be created and populated in Activity or Fragment (this sample does not support XML layouting). I use very simple child views to keep the sample short.

Result

When I run the sample on a device the result is

grid layout

The parent activity background is set to yellow color. The root layout of activity has some paddings (without those paddings the smile won’t look so good).

Limitations

This is a very basic example and many features are still missing

  1. There is no support for declaring the grid and it’s children in XML.
  2. There is no support for putting the grid into scroll view.
  3. No validation is done.
  4. Some pixels are lost during rounding operations.
  5. There is no support for gravity of child views.
Lifehack for Android Developers: WeigthedGridLayout