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:
- Tell the
TextView
ITSELF to center its own contents horizontally within the view bounds - 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!