Android Layout Relationships

Dave Smith
Dave Smith

Developing UI layouts for Android is an experience unlike any other. I have developed for both desktop and mobile on a variety of platforms, and the XML structure that Android uses is quite unique. This can bring with it some issues and challenges as it runs contrary to the way many people think about designing their UI.

Today, I'm going to make some comments on questions that I see constantly regarding the XML keywords most commonly misused in creating layouts. I'm going to focus on developing using XML, but the same rules apply when creating LayoutParams in code.

Me Or My Parent?

When laying out elements (or widgets) on the screen, it usually doesn't take long for people to realize that there are two of many of the basic parameters associated with size and location. Options like width, height, and gravity have parallel values named layout_width, layout_height, and layout_gravity; so what gives? Parameters with the prefix layout_ are actually instructions that are to be passed to the PARENT of the object that they are placed on, while all other parameters are passed to the object itself.

This can be a source of confusion even when you want to do something as simple as center some text, so let's look at an example. Imagine we have a simple layout like the one listed below:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  <TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:text="My Text Content"
  />
</LinearLayout>

We placed the constraint layout_gravity="center_horizontal" so that the text would be centered on the screen, but if this layout gets rendered, the results are not as expected! Why? Well, in the example the TextView told the following to its parent LinearLayout:

  • Make me as wide as you are (layout_width="fill_parent")
  • Make me just tall enough to fit the text inside (layout_height="wrap_content")
  • Lay me out centered horizontally (layout_gravity="center_horizontal")

Points #1 and #3 are actually in direct opposition to each other. The TextView has asked to be centered within the LinearLayout, but also be just as wide (so there is really no room to center it). What we really wanted to do was to either:

  1. Tell the TextView ITSELF to center its own contents horizontally within the view bounds
  2. Tell the TextView to be JUST as wide as its text, and them center the whole view horizontally in the parent.

Example Fix #1

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  <TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:text="My Text Content"
  />
</LinearLayout>

Example Fix #2

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:text="My Text Content"
  />
</LinearLayout>

Bottom Line: Remember that any parameter that starts with layout_ is actually an instruction for the parent view, and not the view where it is located!