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