Home | History | Annotate | Download | only in tv
      1 page.title=Optimizing Layouts for TV
      2 parent.title=Designing for TV
      3 parent.link=index.html
      4 
      5 trainingnavtop=true
      6 next.title=Optimizing Navigation for TV
      7 next.link=optimizing-navigation-tv.html
      8 
      9 @jd:body
     10 
     11 <div id="tb-wrapper">
     12 <div id="tb">
     13 
     14 <h2>This lesson teaches you to</h2>
     15 <ol>
     16   <li><a href="#DesignLandscapeLayouts">Design Landscape Layouts</a></li>
     17   <li><a href="#MakeTextControlsEasyToSee">Make Text and Controls Easy to See</a></li>
     18   <li><a href="#DesignForLargeScreens">Design for High-Density Large Screens</a></li>
     19   <li><a href="#HandleLargeBitmaps">Design to Handle Large Bitmaps</a></li>
     20 </ol>
     21 
     22 <h2>You should also read</h2>
     23 <ul>
     24   <li><a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a></li>
     25 </ul>
     26 
     27 </div>
     28 </div>
     29 
     30 <p>
     31 When your application is running on a television set, you should assume that the user is sitting about 
     32 ten feet away from the screen. This user environment is referred to as the 
     33 <a href="http://en.wikipedia.org/wiki/10-foot_user_interface">10-foot UI</a>. To provide your 
     34 users with a usable and enjoyable experience, you should style and lay out your UI accordingly..
     35 </p>
     36 <p>
     37 This lesson shows you how to optimize layouts for TV by:
     38 </p>
     39 <ul>
     40   <li>Providing appropriate layout resources for landscape mode.</li>
     41   <li>Ensuring that text and controls are large enough to be visible from a distance.</li>
     42   <li>Providing high resolution bitmaps and icons for HD TV screens.</li>
     43 </ul>
     44 
     45 <h2 id="DesignLandscapeLayouts">Design Landscape Layouts</h2> 
     46 
     47 <p>
     48 TV screens are always in landscape orientation. Follow these tips to build landscape layouts optimized for TV screens:
     49 </p> 
     50 <ul>
     51   <li>Put on-screen navigational controls on the left or right side of the screen and save the 
     52   vertical space for content.</li>
     53   <li>Create UIs that are divided into sections, by using <a href="{@docRoot}guide/components/fragments.html">Fragments</a> 
     54   and use view groups like {@link android.widget.GridView} instead 
     55   of {@link android.widget.ListView} to make better use of the 
     56   horizontal screen space.</li>
     57   <li>Use view groups such as {@link android.widget.RelativeLayout} 
     58   or {@link android.widget.LinearLayout} to arrange views. 
     59   This allows the Android system to adjust the position of the views to the size, alignment, 
     60   aspect ratio, and pixel density of the TV screen.</li>
     61   <li>Add sufficient margins between layout controls to avoid a cluttered UI.</li>
     62 </ul> 
     63  
     64 <p>
     65 For example, the following layout is optimized for TV:
     66 </p>
     67 
     68 <img src="{@docRoot}images/training/panoramio-grid.png" />
     69 
     70 <p>
     71 In this layout, the controls are on the lefthand side. The UI is displayed within a 
     72 {@link android.widget.GridView}, which is well-suited to landscape orientation.
     73 In this layout both GridView and Fragment have the width and height set 
     74 dynamically, so they can adjust to the screen resolution. Controls are added to the left side Fragment programatically at runtime.
     75 The layout file for this UI is {@code res/layout-land-large/photogrid_tv.xml}.
     76 (This layout file is placed in {@code layout-land-large} because TVs have large screens with landscape orientation. For details refer to 
     77 <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.)</p>
     78 
     79 res/layout-land-large/photogrid_tv.xml
     80 <pre>
     81 &lt;RelativeLayout
     82     android:layout_width="fill_parent"
     83     android:layout_height="fill_parent" &gt;
     84 
     85     &lt;fragment
     86         android:id="@+id/leftsidecontrols"
     87         android:layout_width="0dip"
     88         android:layout_marginLeft="5dip"
     89         android:layout_height="match_parent" /&gt;
     90 
     91     &lt;GridView        
     92         android:id="@+id/gridview"
     93         android:layout_width="wrap_content"
     94         android:layout_height="wrap_content" /&gt;
     95 
     96 &lt;/RelativeLayout>
     97 </pre>
     98 
     99 <p>
    100 To set up action bar items on the left side of the screen, you can also include the <a
    101 href="http://code.google.com/p/googletv-android-samples/source/browse/#git%2FLeftNavBarLibrary">
    102 Left navigation bar library</a> in your application to set up action items on the left side 
    103 of the screen, instead of creating a custom Fragment to add controls:
    104 </p>
    105 
    106 <pre>
    107 LeftNavBar bar = (LeftNavBarService.instance()).getLeftNavBar(this);
    108 </pre>
    109 
    110 <p>
    111 When you have an activity in which the content scrolls vertically, always use a left navigation bar; 
    112 otherwise, your users have to scroll to the top of the content to switch between the content view and 
    113 the ActionBar. Look at the  
    114 <a href="http://code.google.com/p/googletv-android-samples/source/browse/#git%2FLeftNavBarDemo">
    115 Left navigation bar sample app</a> to see how to simple it is to include the left navigation bar in your app.
    116 </p>
    117 
    118 <h2 id="MakeTextControlsEasyToSee">Make Text and Controls Easy to See</h2>
    119 <p>
    120 The text and controls in a TV application's UI should be easily visible and navigable from a distance.
    121 Follow these tips to make them easier to see from a distance :
    122 </p>
    123 
    124 <ul>
    125   <li>Break text into small chunks that users can quickly scan.</li>
    126   <li>Use light text on a dark background. This style is easier to read on a TV.</li>
    127   <li>Avoid lightweight fonts or fonts that have both very narrow and very broad strokes. Use simple sans-serif 
    128   fonts and use anti-aliasing to increase readability.</li>
    129   <li>Use Android's standard font sizes:
    130   <pre>
    131   &lt;TextView
    132         android:id="@+id/atext"
    133         android:layout_width="wrap_content"
    134         android:layout_height="wrap_content"
    135         android:gravity="center_vertical"
    136         android:singleLine="true"
    137         android:textAppearance="?android:attr/textAppearanceMedium"/&gt;
    138   </pre></li>
    139   <li>Ensure that all your view widgets are large enough to be clearly visible to someone sitting 10 feet away 
    140   from the screen (this distance is greater for very large screens).  The best way to do this is to use 
    141   layout-relative sizing rather than absolute sizing, and density-independent pixel units instead of absolute 
    142   pixel units. For example, to set the width of a widget, use wrap_content instead of a pixel measurement, 
    143   and to set the margin for a widget, use dip instead of px values.
    144   </li>
    145 </ul>
    146 <p>
    147 
    148 </p>
    149 
    150 <h2 id="DesignForLargeScreens">Design for High-Density Large Screens</h2>
    151 
    152 <p>
    153 The common HDTV display resolutions are 720p, 1080i, and 1080p. Design your UI for 1080p, and then 
    154 allow the Android system to downscale your UI to 720p if necessary. In general, downscaling (removing pixels) 
    155 does not degrade the UI (Notice that the converse is not true; you should avoid upscaling because it degrades 
    156 UI quality).
    157 </p>
    158 
    159 <p>
    160 To get the best scaling results for images, provide them as <a href="{@docRoot}tools/help/draw9patch.html">
    161 9-patch image</a> elements if possible.
    162 If you provide low quality or small images in your layouts, they will appear pixelated, fuzzy, or grainy. This 
    163 is not a good experience for the user. Instead, use high-quality images. 
    164 </p>
    165 
    166 <p>
    167 For more information on optimizing apps for large screens see <a href="{@docRoot}training/multiscreen/index.html">
    168 Designing for multiple screens</a>.
    169 </p>
    170 
    171 <h2 id="HandleLargeBitmaps">Design to Handle Large Bitmaps</h2>
    172 
    173 <p>
    174 The Android system has a limited amount of memory, so downloading and storing high-resolution images can often 
    175 cause out-of-memory errors in your app. To avoid this, follow these tips:
    176 </p>
    177 
    178 <ul>
    179   <li>Load images only when they're displayed on the screen. For example, when displaying multiple images in 
    180       a {@link android.widget.GridView} or 
    181       {@link android.widget.Gallery}, only load an image when 
    182       {@link android.widget.Adapter#getView(int, View, ViewGroup) getView()} 
    183       is called on the View's {@link android.widget.Adapter}.
    184   </li>
    185   <li>Call {@link android.graphics.Bitmap#recycle()} on 
    186       {@link android.graphics.Bitmap} views that are no longer needed.
    187   </li>
    188   <li>Use {@link java.lang.ref.WeakReference} for storing references 
    189       to {@link android.graphics.Bitmap} objects in an in-memory 
    190       {@link java.util.Collection}.</li>
    191   <li>If you fetch images from the network, use {@link android.os.AsyncTask} 
    192       to fetch them and store them on the SD card for faster access.
    193       Never do network transactions on the application's UI thread.
    194   </li>
    195   <li>Scale down really large images to a more appropriate size as you download them; otherwise, downloading the image 
    196   itself may cause an "Out of Memory" exception. Here is sample code that scales down images while downloading:
    197   
    198   <pre>
    199   // Get the source image's dimensions
    200   BitmapFactory.Options options = new BitmapFactory.Options();
    201   // This does not download the actual image, just downloads headers.
    202   options.inJustDecodeBounds = true; 
    203   BitmapFactory.decodeFile(IMAGE_FILE_URL, options);
    204   // The actual width of the image.
    205   int srcWidth = options.outWidth;  
    206   // The actual height of the image.
    207   int srcHeight = options.outHeight;  
    208 
    209   // Only scale if the source is bigger than the width of the destination view.
    210   if(desiredWidth > srcWidth)
    211     desiredWidth = srcWidth;
    212 
    213   // Calculate the correct inSampleSize/scale value. This helps reduce memory use. It should be a power of 2.
    214   int inSampleSize = 1;
    215   while(srcWidth / 2 > desiredWidth){
    216     srcWidth /= 2;
    217     srcHeight /= 2;
    218     inSampleSize *= 2;
    219   }
    220 
    221   float desiredScale = (float) desiredWidth / srcWidth;
    222 
    223   // Decode with inSampleSize
    224   options.inJustDecodeBounds = false;
    225   options.inDither = false;
    226   options.inSampleSize = inSampleSize;
    227   options.inScaled = false;
    228   // Ensures the image stays as a 32-bit ARGB_8888 image.
    229   // This preserves image quality.
    230   options.inPreferredConfig = Bitmap.Config.ARGB_8888;  
    231                                                 	
    232   Bitmap sampledSrcBitmap = BitmapFactory.decodeFile(IMAGE_FILE_URL, options);
    233 
    234   // Resize
    235   Matrix matrix = new Matrix();
    236   matrix.postScale(desiredScale, desiredScale);
    237   Bitmap scaledBitmap = Bitmap.createBitmap(sampledSrcBitmap, 0, 0,
    238       sampledSrcBitmap.getWidth(), sampledSrcBitmap.getHeight(), matrix, true);
    239   sampledSrcBitmap = null;
    240 
    241   // Save
    242   FileOutputStream out = new FileOutputStream(LOCAL_PATH_TO_STORE_IMAGE);
    243   scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
    244   scaledBitmap = null;
    245    </pre>
    246   </li> </ul>