Home | History | Annotate | Download | only in articles
      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 &mdash; or worse, every layout 
     14 manager &mdash; 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">&lt;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"&gt;
     44     
     45     &lt;ImageView
     46         android:id="&#64;+id/icon"
     47         
     48         android:layout_width="wrap_content"
     49         android:layout_height="fill_parent"
     50         android:layout_marginRight="6dip"
     51         
     52         android:src="&#64;drawable/icon" /&gt;
     53 
     54     &lt;LinearLayout
     55         android:orientation="vertical"
     56     
     57         android:layout_width="0dip"
     58         android:layout_weight="1"
     59         android:layout_height="fill_parent"&gt;
     60 
     61         &lt;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" /&gt;
     68             
     69         &lt;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" /&gt;
     77             
     78     &lt;/LinearLayout&gt;
     79 
     80 &lt;/LinearLayout&gt;</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">&lt;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"&gt;
     93     
     94     &lt;ImageView
     95         android:id="&#64;+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="&#64;drawable/icon" /&gt;
    105 
    106     &lt;TextView  
    107         android:id="&#64;+id/secondLine"
    108 
    109         android:layout_width="fill_parent"
    110         android:layout_height="26dip" 
    111         
    112         android:layout_toRightOf="&#64;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" /&gt;
    119 
    120     &lt;TextView
    121         android:layout_width="fill_parent"
    122         android:layout_height="wrap_content"
    123         
    124         android:layout_toRightOf="&#64;id/icon"
    125         android:layout_alignParentRight="true"
    126         android:layout_alignParentTop="true"
    127         android:layout_above="&#64;id/secondLine"
    128         android:layout_alignWithParentIfMissing="true"
    129                 
    130         android:gravity="center_vertical"
    131         android:text="My Application" /&gt;
    132 
    133 &lt;/RelativeLayout&gt;</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