diff options
Diffstat (limited to 'docs/html/resources/articles/layout-tricks-efficiency.jd')
-rw-r--r-- | docs/html/resources/articles/layout-tricks-efficiency.jd | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/docs/html/resources/articles/layout-tricks-efficiency.jd b/docs/html/resources/articles/layout-tricks-efficiency.jd new file mode 100644 index 0000000..b7b5761 --- /dev/null +++ b/docs/html/resources/articles/layout-tricks-efficiency.jd @@ -0,0 +1,177 @@ +page.title=Layout Tricks: Creating Efficient Layouts +@jd:body + +<p>The Android UI toolkit offers several layout managers that are +rather easy to use and, most of the time, you only need the basic +features of these layout managers to implement a user interface.</p> + +<p>Sticking to the basic features is unfortunately not the most efficient +way to create user interfaces. A common example is the abuse of +{@link android.widget.LinearLayout}, which leads to a proliferation of +views in the view hierarchy. Every view — or worse, every layout +manager — that you add to your application comes at a cost: +initialization, layout and drawing become slower. The layout pass can be +especially expensive when you nest several <code>LinearLayout</code> +that use the {@link android.R.attr#layout_weight weight} +parameter, which requires the child to be measured twice.</p> + +<p>Let's consider a very simple and common example of a layout: a list item +with an icon on the left, a title at the top and an optional description +underneath the title. Here is what such an item looks like:</p> + +<div style="text-align: center;"><img src="images/relativelayout_1.png" alt="Simple list item"></div> + +<p>To clearly understand how the views, one {@link android.widget.ImageView} and +two {@link android.widget.TextView}, are positioned with respect to each other, +here is the wireframe of the layout as captured by <a +href="{@docRoot}guide/developing/tools/hierarchy-viewer.html">HierarchyViewer</a +>:</p> + +<div style="text-align: center;"><img src="images/relativelayout_wire_1.png" alt="Wireframe of the simple list item"></div> + +<p>Implementing this layout is straightforward with <code>LinearLayout</code>. +The item itself is a horizontal <code>LinearLayout</code> with an +<code>ImageView</code> and a vertical <code>LinearLayout</code>, which contains +the two <code>TextView</code>. Here's the source code of this layout:</p> + +<pre class="prettyprint"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="?android:attr/listPreferredItemHeight" + + android:padding="6dip"> + + <ImageView + android:id="@+id/icon" + + android:layout_width="wrap_content" + android:layout_height="fill_parent" + android:layout_marginRight="6dip" + + android:src="@drawable/icon" /> + + <LinearLayout + android:orientation="vertical" + + android:layout_width="0dip" + android:layout_weight="1" + android:layout_height="fill_parent"> + + <TextView + android:layout_width="fill_parent" + android:layout_height="0dip" + android:layout_weight="1" + + android:gravity="center_vertical" + android:text="My Application" /> + + <TextView + android:layout_width="fill_parent" + android:layout_height="0dip" + android:layout_weight="1" + + android:singleLine="true" + android:ellipsize="marquee" + android:text="Simple application that shows how to use RelativeLayout" /> + + </LinearLayout> + +</LinearLayout></pre> + +<p>This layout works but can be wasteful if you instantiate it for every list +item of a {@link android.widget.ListView}. The same layout can be rewritten +using a single {@link android.widget.RelativeLayout}, thus saving one view, and +even better one level in view hierarchy, per list item. The implementation of +the layout with a <code>RelativeLayout</code> remains simple:</p> + +<pre class="prettyprint"><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="?android:attr/listPreferredItemHeight" + + android:padding="6dip"> + + <ImageView + android:id="@+id/icon" + + android:layout_width="wrap_content" + android:layout_height="fill_parent" + + android:layout_alignParentTop="true" + android:layout_alignParentBottom="true" + android:layout_marginRight="6dip" + + android:src="@drawable/icon" /> + + <TextView + android:id="@+id/secondLine" + + android:layout_width="fill_parent" + android:layout_height="26dip" + + android:layout_toRightOf="@id/icon" + android:layout_alignParentBottom="true" + android:layout_alignParentRight="true" + + android:singleLine="true" + android:ellipsize="marquee" + android:text="Simple application that shows how to use RelativeLayout" /> + + <TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + + android:layout_toRightOf="@id/icon" + android:layout_alignParentRight="true" + android:layout_alignParentTop="true" + android:layout_above="@id/secondLine" + android:layout_alignWithParentIfMissing="true" + + android:gravity="center_vertical" + android:text="My Application" /> + +</RelativeLayout></pre> + +<p>This new implementation behaves exactly the same way as the previous +implementation, except in one case. The list item we want to display has two +lines of text: the title and an <em>optional</em> description. When a +description is not available for a given list item, the application would simply +set the visibility of the second <code>TextView</code> to +{@link android.view.View#GONE}. This works perfectly with the <code>LinearLayout</code> +implementation but not with the <code>RelativeLayout</code> version:</p> + +<div style="text-align: center;"><img src="images/relativelayout_2.png" alt="RelativeLayout and description GONE"></div> +<div style="text-align: center;"><img src="images/relativelayout_wire_2.png" alt="RelativeLayout and description GONE"></div> + +<p>In a <code>RelativeLayout</code>, views are aligned with their parent, with the +<code>RelativeLayout</code> itself, or with other views. For instance, we declared that +the description is aligned with the bottom of the <code>RelativeLayout</code> and +that the title is positioned above the description and anchored to the +parent's top. With the description GONE, RelativeLayout doesn't know +where to position the title's bottom edge. To solve this problem, you +can use a very special layout parameter called +{@link android.R.attr#layout_alignWithParentIfMissing}. +</p> + +<p>This boolean parameter simply tells RelativeLayout to use its own edges as +anchors when a constraint target is missing. For instance, if you position a +view to the right of a GONE view and set <code>alignWithParentIfMissing</code> +to <code>true</code>, <code>RelativeLayout</code> will instead anchor the view +to its left edge. In our case, using <code>alignWithParentIfMissing</code> will +cause <code>RelativeLayout</code> to align the title's bottom with its own +bottom. The result is the following:</p> + +<div style="text-align: center;"><img src="images/relativelayout_3.png" alt="RelativeLayout, description GONE and alignWithParentIfMissing"></div> +<div style="text-align: center;"><img src="images/relativelayout_wire_3.png" alt="RelativeLayout, description GONE and alignWithParentIfMissing"></div> + +<p>The +behavior of our layout is now perfect, even when the description is +GONE. Even better, the hierarchy is simpler and because we are not +using LinearLayout's weights it's also more efficient. The difference +between the two implementations becomes obvious when comparing the view +hierarchies in HierarchyViewer:</p> + +<div style="text-align: center;"><img src="images/layouts_comparison_small.png" alt="LinearLayout vs RelativeLayout"></div> + +<p>Again, the difference will be much more important when you use such a layout +for every item in a ListView for instance. Hopefully this simple +example showed you that getting to know your layouts is the best way to +learn how to optimize your UI.</p> |