Layout Types Part 4: FrameLayout

In the previous articles in this series we have looked at LinearLayout, TableLayout, and RelativeLayout. In this concluding part, we’ll look at FrameLayout, which is arguable the simplest of the basic layout types, but can be extremely useful.

When we looked at RelativeLayout, we encountered a problem when trying to align to the bottom of a RelativeLayout with android:layout_height=”wrap_content”. FrameLayout allows us to overcome this problem. Aside from setting margins and padding, FrameLayout provides a single mechanism for positioning children within it: layout_gravity which is similar to the align to parent attributes in RelativeLayout. By setting this value we can control where the children are positioned within the layout:

<FrameLayout 
	android:layout_height="wrap_content"
	android:layout_width="match_parent"
	android:layout_weight="1">
	<TextView android:text="TopLeft" 
		android:layout_width="wrap_content"
		android:layout_height="wrap_content" />
	<TextView android:layout_height="wrap_content"
		android:layout_width="wrap_content" 
		android:text="TopRight"
		android:layout_gravity="top|right" />
	<TextView android:layout_height="wrap_content"
		android:layout_width="wrap_content" 
		android:text="TopCentre"
		android:layout_gravity="top|center_horizontal" />
	<TextView android:text="Left" 
		android:layout_gravity="left|center_vertical"
		android:layout_width="wrap_content" 
		android:layout_height="wrap_content" />
	<TextView android:layout_height="wrap_content"
		android:layout_width="wrap_content" 
		android:text="Right" 
		android:layout_gravity="right|center_vertical" />
	<TextView android:layout_height="wrap_content"
		android:layout_width="wrap_content" 
		android:text="Centre"
		android:layout_gravity="center" />
	<TextView android:text="BottomLeft" 
		android:layout_gravity="left|bottom"
		android:layout_width="wrap_content" 
		android:layout_height="wrap_content" />
	<TextView android:layout_height="wrap_content"
		android:layout_width="wrap_content" 
		android:text="BottomRight" 
		android:layout_gravity="right|bottom" />
	<TextView android:layout_height="wrap_content"
		android:layout_width="wrap_content" 
		android:text="BottomCenter"
		android:layout_gravity="center|bottom" />
</FrameLayout>

As you can see, gravity values can be combined with the “|” symbol. I won’t bother to explain each of these, as I think that they are fairly self-explanatory. If we run it we see:

layout_gravity

layout_gravity

It is worth mentioning that LinearLayout also supports layout_gravity and the usage is identical to how we use it for FrameLayout.

One major difference should be apparent with RelativeLayout: we can align to the bottom, even though the FrameLayout has its height set to wrap_content. This is because the order in which the layout and children’s sizes are calculated is different to RelativeLayout. Moreover, and this is a key factor in what makes FrameLayout useful, the size of the FrameLayout is the size of its largest child (plus padding). You can specify whether or not FrameLayout should include children whose visibility is set to GONE by calling setMeasureAllChildren() or through the android:measureAllChildren attribute in XML. The default is to only measure children whose visibility is set to VISIBLE or INVISIBLE.

The problem with FrameLayout is that the layout behaviour becomes somewhat difficult to understand if it contains multiple children (the documentation for FrameLayout states that scalable layouts using FrameLayout can be tricky). However, our old friend LinearLayout also supports a similar behaviour, and we can use this to solve another common problem: Where we have two View objects, one of which has a variable height, and we want the height of the second view to match the height of the first. For example, we have a TextView which contains text of variable length (and so the height may vary when the number of lines of text changes) and we have an ImageView containing either a 9-patch or XML vector drawable which we want to dynamically match the height of the TextView. We can certainly achieve this programatically, but we can achieve the same thing purely in layout:

<LinearLayout android:layout_width="match_parent"
	android:layout_height="wrap_content" 
	android:padding="5dp">
	<ImageView android:layout_marginRight="5dp"
		android:layout_height="match_parent"
		android:src="@drawable/line" 
		android:layout_width="5dp" />
	<TextView android:layout_height="wrap_content"
		android:layout_width="match_parent" 
		android:text="This is some short text" />
</LinearLayout>
<LinearLayout android:layout_width="match_parent"
	android:layout_height="wrap_content" 
	android:padding="5dp">
	<ImageView android:layout_marginRight="5dp"
		android:layout_height="match_parent"
		android:src="@drawable/line" 
		android:layout_width="5dp" />
	<TextView android:layout_height="wrap_content"
		android:layout_width="match_parent" 
		android:text="This is some much longer text which should spread on to multiple lines so that we can see how the line to the left matches the height of this TextView" />
</LinearLayout>

This uses a very simple vector drawable in res/drawable/line.xml:

?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
	android:shape="rectangle">
	<solid android:color="@android:color/white" />
</shape>

The parent LinearLayout has it’s layout_height set to wrap_content, the TextView’s is also set to wrap_content, and the ImageView’s is set to match_parent. As we can see, this causes the ImageView‘s height to match that of the TextView:

Matching heights

Matching heights

That concludes or tour of the basic layout types in Android. If you are wondering why I haven’t covered some other types such as Gallery, GridView, and ListView it is because I am focussing purely on the layout, which is the purpose of this series. These advanced controls are data-bound widgets which build on top of these basic layout mechanisms and will be the subject of future articles.

The source code for this article can be found here.

© 2011, Mark Allison. All rights reserved. This article originally appeared on Styling Android.

Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License

DeliciousStumbleUponRedditDiggBookmark/FavoritesShare

Creative Commons License
Layout Types Part 4: FrameLayout by Styling Android, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. Terms and conditions beyond the scope of this license may be available at blog.stylingandroid.com.

Tags: ,

2 Responses to “Layout Types Part 4: FrameLayout”

  1. Wallace Espindola says:

    Hi Mark,

    I´ve met you at the AndroidConf Brasil, and I was taking a look at you blog, to get some layout tips, when I got an error at the “layout_gravity” image. “Botton Left” text is positioned at the both sides, left and right. Take a look on that later… ;-)

    Regards,
    Wallace Espindola.

    • Mark Allison says:

      Hi Wallace,

      AndroidConf was amazing – I had such a great time, and really enjoyed meeting lots of cool Android developers.

      Thanks for spotting the error – it should be fixed now.

      Best regards,

      Mark

Leave a Reply