mattias | niklewski.com

Android layout colorizer

Update 2012-12-02: In Jelly Bean there is a new developer option called "Show layout bounds" that shows view bounds + margins. It's awesome and all but obsoletes this technique.

Despite the SDK developer's best intentions, creating and debugging Android layouts is something of an art. In this post I show a crude but useful utility that applies random background colors to quickly find layout bugs.

I will assume that you have done your homework and that you understand how View and ViewGroup objects combine to form a view tree.

A Random Walk Down View Street

If the hierarchy viewer is the interactive debugger of layouts, changing background colors is like debugging by print statements -- simplistic, yet surprisingly effective.

This is the first thing I try when I see a layout problem.

<TextView
    android:background="#ff0000"
    ...

It is often enough to see what causes that unintentional gap between your views. It could be a margin, a padding, or perhaps an incorrect gravity value.

Background colors help explain things to your visual designer, too. Maybe your designer expects adjacent margins to collapse, HTML style, when in fact they will not. Or he might ask you to use a certain size margin around a list, but forget to take the padding of the surrounding element into account. "Wait, why is the padding so large?" In my experience, adding colored boxes makes it easy to explain what's going on.

Adding the colors one view at a time gets tedious. We can do better. Here is a method that acts on a whole view tree.

private static Random r = new Random();

private void dbgColorize(View view, boolean overwrite) {
    Drawable bg = view.getBackground();
    if (overwrite || (bg == null || bg instanceof ColorDrawable)) {
        view.setBackgroundColor(Color.argb(0xa0,
                0xb0 + r.nextInt(0x40),
                0xb0 + r.nextInt(0x40),
                0xb0 + r.nextInt(0x40)));
    }

    if (view instanceof ViewGroup) {
        ViewGroup vg = (ViewGroup)view;
        for (int i = 0; i < vg.getChildCount(); i++) {
            dbgColorize(vg.getChildAt(i), overwrite);
        }
    }
}

It uses translucent, bright pastel colors to light your view up like a Christmas tree. If your corporate environment cannot handle all this awesome color, call setBackgroundColor with 0x80ffffff for a monochrome feel.

Set up an entry point and point dbgColorize at the root of the view tree you want colorized:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == R.id.dbg_colorize) {
        dbgColorize(getWindow().getDecorView(), true);
        ...

By default dbgColorize is careful not to touch views that already have a background, like buttons. You can pass overwrite = true to override.

An Example

Here is a simple layout with some alignment problems. The right side shows the same layout after dbgColorize.

In the colorized version, we can start to guess what is going on. The Button is in fact left-aligned with the "Header", but it looks a little off due to a large leftPadding, which must come from its 9-patch background. The ListView has a combined left margin and padding that aligns nicely with the "Header", but then the list items have an additional padding that pushes them too far in.

I have been using dbgColorize for a few months now. So far the only downside is having to manually hook up and remove the debug code. With git though, you can do it once and keep the result on a local branch. Then it is always just a cherry-pick away.