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