MATCH_PARENT vs FILL_PARENT: What Not to Do and What to Do
(Updated with technical correction from Roman Mazur. Thanks, Roman.)
Here's the short of it: unless you are compiling against Froyo (API 8), please stop using FILL_PARENT
to specify layout_width
and layout_height
. Use MATCH_PARENT
. They have the same integer value, but FILL_PARENT
is deprecated and the name itself is misleading. Please, use MATCH_PARENT
.
Why you should just use MATCH_PARENT
Alright, if you are still reading then I am assuming that you are not compiling against Froyo and that either you do not understand or do not agree with me being so down on FILL_PARENT
.
So MATCH_PARENT
and FILL_PARENT
are the same?
Yes, MATCH_PARENT
and FILL_PARENT
are just different constant names for the same integer value (-1 if you are curious) used to specify a View
's layout mode within its parent.
So why was MATCH_PARENT
added?
The Android team found that developers were misinterpreting FILL_PARENT
to mean that a View
would fill the remaining space left in its parent. In fact, by specifying FILL_PARENT
, the View
is requesting to be as big as its parent. Thus, (as explained by Romain Guy himself in this video at around 10:56) the constant was renamed MATCH_PARENT
to clarify its use.
Okay, I get how FILL_PARENT
/MATCH_PARENT
works. What does it matter if I use one or the other?
FILL_PARENT
is deprecated. Being deprecated does not make it the Devil, but eventually it will go away. Your application is more future-proof using MATCH_PARENT
. Why use the deprecated option when the current option behaves exactly the same?
Furthermore, FILL_PARENT
is actually misleading. I have personally seen folks confused because it does not work the way they thought it would. In fact, I have seen a single tag using both FILL_PARENT
and MATCH_PARENT
, because the developer thought (understandably) that they were two different layout modes.
Be current. Be clear. Use MATCH_PARENT
.
How you can get tripped up trying to FILL_PARENT
Here's a quick example of how MATCH_PARENT
/FILL_PARENT
confusion can lead to folks repeatedly applying their heads to their desks. First, take a really simple layout containing a few View
instances.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#FFFF00" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:background="@android:color/black"
android:text="@string/hello_world"
android:padding="50dp" />
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF0000" />
</LinearLayout>
And this is what it looks when run on a device.
Woah, you set that red View
to MATCH_PARENT
and it filled the remaining space in the LinearLayout
. It's not as big as its parent. What gives?
And here's the confusion. LinearLayout
lays out its children sequentially, the start position of a child being the end position of the previous child. A child requests that the parent give it certain dimensions, but this does not effect where the child is positioned. Since the red View is third, it is laid out after the first two, and thus, ends up not as "big as parent."
This is a consequence of position, not of how MATCH_PARENT
/FILL_PARENT
works. The LinearLayout
honors the requests of its child Views the best it can, but cannot guarantee them.
Now, let us see what happens when we switch things around by making the red View
first in the layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF0000" />
<View
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#FFFF00" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:background="@android:color/black"
android:text="@string/hello_world"
android:padding="50dp" />
</LinearLayout>
Now here is what it looks like, and it is easy to see the difference. Since the LinearLayout
lays out the red View first, it positions it at the top and can fully meet its MATCH_PARENT
request. That results in the red View
pushing the other two out of sight.
Okay, so what if I actually want to make a View
fill the remaining space in its parent?
How to actually "fill parent"
The general strategy for implementing "fill parent" is to use a LinearLayout
and the layout_weight
attribute. Now we will use them to fix our second layout that was taken over by the Blob (that red View
).
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#FF0000" />
<View
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#FFFF00" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:background="@android:color/black"
android:text="@string/hello_world"
android:padding="50dp" />
</LinearLayout>
Here we were able to keep the red View
as the first child in the LinearLayout
and have it only fill the space remaining after laying out the other two views.
Really there is never just one way to create a layout. If we wanted to just make the red View
last in the LinearLayout
and have it fill the remaining space, we could have used the first layout, end of story. However, it is important to understand why it works and when it might not work.
(Weights are really handy, and you can use them with one or more View
instances. If anyone is interested in another longwinded post about layout_weight
tips and tricks please leave me some feedback or send me an email.)