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