1page.title=Layout Tricks: Creating Efficient Layouts 2parent.title=Articles 3parent.link=../browser.html?tag=article 4@jd:body 5 6<p>The Android UI toolkit offers several layout managers that are 7rather easy to use and, most of the time, you only need the basic 8features of these layout managers to implement a user interface.</p> 9 10<p>Sticking to the basic features is unfortunately not the most efficient 11way to create user interfaces. A common example is the abuse of 12{@link android.widget.LinearLayout}, which leads to a proliferation of 13views in the view hierarchy. Every view — or worse, every layout 14manager — that you add to your application comes at a cost: 15initialization, layout and drawing become slower. The layout pass can be 16especially expensive when you nest several <code>LinearLayout</code> 17that use the {@link android.R.attr#layout_weight weight} 18parameter, which requires the child to be measured twice.</p> 19 20<p>Let's consider a very simple and common example of a layout: a list item 21with an icon on the left, a title at the top and an optional description 22underneath the title. Here is what such an item looks like:</p> 23 24<div style="text-align: center;"><img src="images/relativelayout_1.png" alt="Simple list item"></div> 25 26<p>To clearly understand how the views, one {@link android.widget.ImageView} and 27two {@link android.widget.TextView}, are positioned with respect to each other, 28here is the wireframe of the layout as captured by <a 29href="{@docRoot}guide/developing/tools/hierarchy-viewer.html">HierarchyViewer</a 30>:</p> 31 32<div style="text-align: center;"><img src="images/relativelayout_wire_1.png" alt="Wireframe of the simple list item"></div> 33 34<p>Implementing this layout is straightforward with <code>LinearLayout</code>. 35The item itself is a horizontal <code>LinearLayout</code> with an 36<code>ImageView</code> and a vertical <code>LinearLayout</code>, which contains 37the two <code>TextView</code>. Here's the source code of this layout:</p> 38 39<pre class="prettyprint"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 40 android:layout_width="fill_parent" 41 android:layout_height="?android:attr/listPreferredItemHeight" 42 43 android:padding="6dip"> 44 45 <ImageView 46 android:id="@+id/icon" 47 48 android:layout_width="wrap_content" 49 android:layout_height="fill_parent" 50 android:layout_marginRight="6dip" 51 52 android:src="@drawable/icon" /> 53 54 <LinearLayout 55 android:orientation="vertical" 56 57 android:layout_width="0dip" 58 android:layout_weight="1" 59 android:layout_height="fill_parent"> 60 61 <TextView 62 android:layout_width="fill_parent" 63 android:layout_height="0dip" 64 android:layout_weight="1" 65 66 android:gravity="center_vertical" 67 android:text="My Application" /> 68 69 <TextView 70 android:layout_width="fill_parent" 71 android:layout_height="0dip" 72 android:layout_weight="1" 73 74 android:singleLine="true" 75 android:ellipsize="marquee" 76 android:text="Simple application that shows how to use RelativeLayout" /> 77 78 </LinearLayout> 79 80</LinearLayout></pre> 81 82<p>This layout works but can be wasteful if you instantiate it for every list 83item of a {@link android.widget.ListView}. The same layout can be rewritten 84using a single {@link android.widget.RelativeLayout}, thus saving one view, and 85even better one level in view hierarchy, per list item. The implementation of 86the layout with a <code>RelativeLayout</code> remains simple:</p> 87 88<pre class="prettyprint"><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 89 android:layout_width="fill_parent" 90 android:layout_height="?android:attr/listPreferredItemHeight" 91 92 android:padding="6dip"> 93 94 <ImageView 95 android:id="@+id/icon" 96 97 android:layout_width="wrap_content" 98 android:layout_height="fill_parent" 99 100 android:layout_alignParentTop="true" 101 android:layout_alignParentBottom="true" 102 android:layout_marginRight="6dip" 103 104 android:src="@drawable/icon" /> 105 106 <TextView 107 android:id="@+id/secondLine" 108 109 android:layout_width="fill_parent" 110 android:layout_height="26dip" 111 112 android:layout_toRightOf="@id/icon" 113 android:layout_alignParentBottom="true" 114 android:layout_alignParentRight="true" 115 116 android:singleLine="true" 117 android:ellipsize="marquee" 118 android:text="Simple application that shows how to use RelativeLayout" /> 119 120 <TextView 121 android:layout_width="fill_parent" 122 android:layout_height="wrap_content" 123 124 android:layout_toRightOf="@id/icon" 125 android:layout_alignParentRight="true" 126 android:layout_alignParentTop="true" 127 android:layout_above="@id/secondLine" 128 android:layout_alignWithParentIfMissing="true" 129 130 android:gravity="center_vertical" 131 android:text="My Application" /> 132 133</RelativeLayout></pre> 134 135<p>This new implementation behaves exactly the same way as the previous 136implementation, except in one case. The list item we want to display has two 137lines of text: the title and an <em>optional</em> description. When a 138description is not available for a given list item, the application would simply 139set the visibility of the second <code>TextView</code> to 140{@link android.view.View#GONE}. This works perfectly with the <code>LinearLayout</code> 141implementation but not with the <code>RelativeLayout</code> version:</p> 142 143<div style="text-align: center;"><img src="images/relativelayout_2.png" alt="RelativeLayout and description GONE"></div> 144<div style="text-align: center;"><img src="images/relativelayout_wire_2.png" alt="RelativeLayout and description GONE"></div> 145 146<p>In a <code>RelativeLayout</code>, views are aligned with their parent, with the 147<code>RelativeLayout</code> itself, or with other views. For instance, we declared that 148the description is aligned with the bottom of the <code>RelativeLayout</code> and 149that the title is positioned above the description and anchored to the 150parent's top. With the description GONE, RelativeLayout doesn't know 151where to position the title's bottom edge. To solve this problem, you 152can use a very special layout parameter called 153{@link android.R.attr#layout_alignWithParentIfMissing}. 154</p> 155 156<p>This boolean parameter simply tells RelativeLayout to use its own edges as 157anchors when a constraint target is missing. For instance, if you position a 158view to the right of a GONE view and set <code>alignWithParentIfMissing</code> 159to <code>true</code>, <code>RelativeLayout</code> will instead anchor the view 160to its left edge. In our case, using <code>alignWithParentIfMissing</code> will 161cause <code>RelativeLayout</code> to align the title's bottom with its own 162bottom. The result is the following:</p> 163 164<div style="text-align: center;"><img src="images/relativelayout_3.png" alt="RelativeLayout, description GONE and alignWithParentIfMissing"></div> 165<div style="text-align: center;"><img src="images/relativelayout_wire_3.png" alt="RelativeLayout, description GONE and alignWithParentIfMissing"></div> 166 167<p>The 168behavior of our layout is now perfect, even when the description is 169GONE. Even better, the hierarchy is simpler and because we are not 170using LinearLayout's weights it's also more efficient. The difference 171between the two implementations becomes obvious when comparing the view 172hierarchies in HierarchyViewer:</p> 173 174<div style="text-align: center;"><img src="images/layouts_comparison_small.png" alt="LinearLayout vs RelativeLayout"></div> 175 176<p>Again, the difference will be much more important when you use such a layout 177for every item in a ListView for instance. Hopefully this simple 178example showed you that getting to know your layouts is the best way to 179learn how to optimize your UI.</p> 180