1 page.title=Layout Tricks: Creating Efficient Layouts 2 @jd:body 3 4 <p>The Android UI toolkit offers several layout managers that are 5 rather easy to use and, most of the time, you only need the basic 6 features of these layout managers to implement a user interface.</p> 7 8 <p>Sticking to the basic features is unfortunately not the most efficient 9 way to create user interfaces. A common example is the abuse of 10 {@link android.widget.LinearLayout}, which leads to a proliferation of 11 views in the view hierarchy. Every view — or worse, every layout 12 manager — that you add to your application comes at a cost: 13 initialization, layout and drawing become slower. The layout pass can be 14 especially expensive when you nest several <code>LinearLayout</code> 15 that use the {@link android.R.attr#layout_weight weight} 16 parameter, 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 19 with an icon on the left, a title at the top and an optional description 20 underneath 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 25 two {@link android.widget.TextView}, are positioned with respect to each other, 26 here is the wireframe of the layout as captured by <a 27 href="{@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>. 33 The item itself is a horizontal <code>LinearLayout</code> with an 34 <code>ImageView</code> and a vertical <code>LinearLayout</code>, which contains 35 the 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 81 item of a {@link android.widget.ListView}. The same layout can be rewritten 82 using a single {@link android.widget.RelativeLayout}, thus saving one view, and 83 even better one level in view hierarchy, per list item. The implementation of 84 the 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 134 implementation, except in one case. The list item we want to display has two 135 lines of text: the title and an <em>optional</em> description. When a 136 description is not available for a given list item, the application would simply 137 set the visibility of the second <code>TextView</code> to 138 {@link android.view.View#GONE}. This works perfectly with the <code>LinearLayout</code> 139 implementation 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 146 the description is aligned with the bottom of the <code>RelativeLayout</code> and 147 that the title is positioned above the description and anchored to the 148 parent's top. With the description GONE, RelativeLayout doesn't know 149 where to position the title's bottom edge. To solve this problem, you 150 can 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 155 anchors when a constraint target is missing. For instance, if you position a 156 view to the right of a GONE view and set <code>alignWithParentIfMissing</code> 157 to <code>true</code>, <code>RelativeLayout</code> will instead anchor the view 158 to its left edge. In our case, using <code>alignWithParentIfMissing</code> will 159 cause <code>RelativeLayout</code> to align the title's bottom with its own 160 bottom. 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 166 behavior of our layout is now perfect, even when the description is 167 GONE. Even better, the hierarchy is simpler and because we are not 168 using LinearLayout's weights it's also more efficient. The difference 169 between the two implementations becomes obvious when comparing the view 170 hierarchies 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 175 for every item in a ListView for instance. Hopefully this simple 176 example showed you that getting to know your layouts is the best way to 177 learn how to optimize your UI.</p> 178