1page.title=Supporting Different Screen Sizes 2parent.title=Designing for Multiple Screens 3parent.link=index.html 4 5trainingnavtop=true 6next.title=Supporting Different Screen Densities 7next.link=screendensities.html 8 9@jd:body 10 11 12<!-- This is the training bar --> 13<div id="tb-wrapper"> 14<div id="tb"> 15 16<h2>This lesson teaches you to</h2> 17<ol> 18 <li><a href="#TaskUseWrapMatchPar">Use "wrap_content" and "match_parent"</a></li> 19 <li><a href="#TaskUseRelativeLayout">Use RelativeLayout</a></li> 20 <li><a href="#TaskUseSizeQuali">Use Size Qualifiers</a></li> 21 <li><a href="#TaskUseSWQuali">Use the Smallest-width Qualifier</a></li> 22 <li><a href="#TaskUseAliasFilters">Use Layout Aliases</a></li> 23 <li><a href="#TaskUseOriQuali">Use Orientation Qualifiers</a></li> 24 <li><a href="#TaskUse9Patch">Use Nine-patch Bitmaps</a></li> 25</ol> 26 27<h2>You should also read</h2> 28 29<ul> 30 <li><a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a></li> 31</ul> 32 33<h2>Try it out</h2> 34 35<div class="download-box"> 36<a href="http://developer.android.com/shareables/training/NewsReader.zip" class="button">Download 37 the sample app</a> 38<p class="filename">NewsReader.zip</p> 39</div> 40 41</div> 42</div> 43 44<p>This lesson shows you how to support different screen sizes by:</p> 45<ul> 46 <li>Ensuring your layout can be adequately resized to fit the screen</li> 47 <li>Providing appropriate UI layout according to screen configuration</li> 48 <li>Ensuring the correct layout is applied to the correct screen</li> 49 <li>Providing bitmaps that scale correctly</li> 50</ul> 51 52 53<h2 id="TaskUseWrapMatchPar">Use "wrap_content" and "match_parent"</h2> 54 55<p>To ensure that your layout is flexible and adapts to different screen sizes, 56you should use <code>"wrap_content"</code> and <code>"match_parent"</code> for the width 57and height of some view components. If you use <code>"wrap_content"</code>, the width 58or height of the view is set to the minimum size necessary to fit the content 59within that view, while <code>"match_parent"</code> makes the component expand to match the size of 60its parent view.</p> 61 62<p>By using the <code>"wrap_content"</code> and <code>"match_parent"</code> size values instead of 63hard-coded sizes, your views either use only the space required for that 64view or expand to fill the available space, respectively. For example:</p> 65 66{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane_with_bar.xml all} 67 68<p>Notice how the sample uses <code>"wrap_content"</code> and <code>"match_parent"</code> 69for component sizes rather than specific dimensions. This allows the layout 70to adapt correctly to different screen sizes and orientations.</p> 71 72<p>For example, this is what this layout looks like in portrait and landscape 73mode. Notice that the sizes of the components adapt automatically to the 74width and height:</p> 75 76<img src="{@docRoot}images/training/layout-hvga.png" /> 77<p class="img-caption"><strong>Figure 1.</strong> The News Reader sample app in portrait (left) 78and landscape (right).</p> 79 80 81<h2 id="TaskUseRelativeLayout">Use RelativeLayout</h2> 82 83<p>You can construct fairly complex layouts using nested instances of {@link 84android.widget.LinearLayout} and 85combinations of <code>"wrap_content"</code> and <code>"match_parent"</code> sizes. 86However, {@link android.widget.LinearLayout} does not allow you to precisely control the 87spacial relationships of child views; views in a {@link android.widget.LinearLayout} simply line up 88side-by-side. If you need child views to be oriented in variations other than a straight line, a 89better solution is often to use a {@link android.widget.RelativeLayout}, which allows 90you to specify your layout in terms of the spacial relationships between 91components. For instance, you can align one child view on the left side and another view on 92the right side of the screen.</p> 93 94<p>For example:</p> 95 96<pre> 97<?xml version="1.0" encoding="utf-8"?> 98<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 99 android:layout_width="match_parent" 100 android:layout_height="match_parent"> 101 <TextView 102 android:id="@+id/label" 103 android:layout_width="match_parent" 104 android:layout_height="wrap_content" 105 android:text="Type here:"/> 106 <EditText 107 android:id="@+id/entry" 108 android:layout_width="match_parent" 109 android:layout_height="wrap_content" 110 android:layout_below="@id/label"/> 111 <Button 112 android:id="@+id/ok" 113 android:layout_width="wrap_content" 114 android:layout_height="wrap_content" 115 android:layout_below="@id/entry" 116 android:layout_alignParentRight="true" 117 android:layout_marginLeft="10dp" 118 android:text="OK" /> 119 <Button 120 android:layout_width="wrap_content" 121 android:layout_height="wrap_content" 122 android:layout_toLeftOf="@id/ok" 123 android:layout_alignTop="@id/ok" 124 android:text="Cancel" /> 125</RelativeLayout> 126</pre> 127 128<p>Figure 2 shows how this layout appears on a QVGA screen.</p> 129 130<img src="{@docRoot}images/training/relativelayout1.png" /> 131<p class="img-caption"><strong>Figure 2.</strong> Screenshot on a QVGA screen (small screen).</p> 132 133<p>Figure 3 shows how it appears on a larger screen.</p> 134 135<img src="{@docRoot}images/training/relativelayout2.png" /> 136<p class="img-caption"><strong>Figure 3.</strong> Screenshot on a WSVGA screen (large screen).</p> 137 138<p>Notice that although the size of the components changed, their 139spatial relationships are preserved as specified by the {@link 140android.widget.RelativeLayout.LayoutParams}.</p> 141 142 143<h2 id="TaskUseSizeQuali">Use Size Qualifiers</h2> 144 145<p>There's only so much mileage you can get from a flexible layout or relative layout 146like the one in the previous sections. While those layouts adapt to 147different screens by stretching the space within and around components, they 148may not provide the best user experience for each screen size. Therefore, your 149application should not only implement flexible layouts, but should also provide 150several alternative layouts to target different screen configurations. You do 151so by using <a href="http://developer.android.com/guide/practices/screens_support.html#qualifiers">configuration qualifiers</a>, which allows the runtime 152to automatically select the appropriate resource based on the current device’s 153configuration (such as a different layout design for different screen sizes).</p> 154 155<p>For example, many applications implement the "two pane" pattern for large 156screens (the app might show a list of items on one pane and the content on 157another pane). Tablets and TVs are large enough for both panes to fit 158simultaneously on screen, but phone screens have to show them separately. So, 159to implement these layouts, you could have the following files:</p> 160 161<ul> 162 <li><code>res/layout/main.xml</code>, single-pane (default) layout: 163 164{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all} 165</li> 166 <li><code>res/layout-large/main.xml</code>, two-pane layout: 167 168{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} 169</li> 170</ul> 171 172<p>Notice the <code>large</code> qualifier in the directory name of the second layout. This layout 173will be selected on devices with screens classified as large (for example, 7" tablets and above). The 174other layout (without qualifiers) will be selected for smaller devices.</p> 175 176 177<h2 id="TaskUseSWQuali">Use the Smallest-width Qualifier</h2> 178 179<p>One of the difficulties developers had in pre-3.2 Android devices was the 180"large" screen size bin, which encompasses the Dell Streak, the original Galaxy 181Tab, and 7" tablets in general. However, many applications may want to show 182different layouts for different devices in this category (such as for 5" and 7" devices), even 183though they are all considered to be "large" screens. That's why Android introduced the 184"Smallest-width" qualifier (amongst others) in Android 3.2.</p> 185 186<p>The Smallest-width qualifier allows you to target screens that have a certain minimum 187width given in dp. For example, the typical 7" tablet has a minimum width of 188600 dp, so if you want your UI to have two panes on those screens (but a single 189list on smaller screens), you can use the same two layouts from the previous section for single 190and two-pane layouts, but instead of the <code>large</code> size qualifier, use 191<code>sw600dp</code> to indicate the two-pane layout is for screens on which the smallest-width 192is 600 dp:</p> 193 194<ul> 195 <li><code>res/layout/main.xml</code>, single-pane (default) layout: 196 197{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all} 198</li> 199 <li><code>res/layout-sw600dp/main.xml</code>, two-pane layout: 200 201{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} 202</li> 203</ul> 204 205<p>This means that devices whose smallest width is greater than or equal to 206600dp will select the <code>layout-sw600dp/main.xml</code> (two-pane) layout, 207while smaller screens will select the <code>layout/main.xml</code> (single-pane) 208layout.</p> 209 210<p>However, this won't work well on pre-3.2 devices, because they don't 211recognize <code>sw600dp</code> as a size qualifier, so you still have to use the <code>large</code> 212qualifier as well. So, you should have a file named 213<code>res/layout-large/main.xml</code> 214which is identical to <code>res/layout-sw600dp/main.xml</code>. In the next section 215you'll see a technique that allows you to avoid duplicating the layout files this way.</p> 216 217 218<h2 id="TaskUseAliasFilters">Use Layout Aliases</h2> 219 220<p>The smallest-width qualifier is available only on Android 3.2 and above. 221Therefore, you should also still use the abstract size bins (small, normal, 222large and xlarge) to be compatible with earlier versions. For example, if you 223want to design your UI so that it shows a single-pane UI on phones but a 224multi-pane UI on 7" tablets, TVs and other large devices, you'd have to supply these 225files:</p> 226 227<p><ul> 228<li><code>res/layout/main.xml:</code> single-pane layout</li> 229<li><code>res/layout-large:</code> multi-pane layout</li> 230<li><code>res/layout-sw600dp:</code> multi-pane layout</li> 231</ul></p> 232 233<p>The last two files are identical, because one of them will be matched by 234Android 3.2 devices, and the other one is for the benefit of tablets and TVs with 235earlier versions of Android.</p> 236 237<p>To avoid this duplication of the same file for tablets and TVs (and the maintenance 238headache resulting from it), you can use alias files. For example, you can define the following 239layouts:</p> 240 241<ul> 242<li><code>res/layout/main.xml</code>, single-pane layout</li> 243<li><code>res/layout/main_twopanes.xml</code>, two-pane layout</li> 244</ul> 245 246<p>And add these two files:</p> 247 248<p><ul> 249<li><code>res/values-large/layout.xml</code>: 250<pre> 251<resources> 252 <item name="main" type="layout">@layout/main_twopanes</item> 253</resources> 254</pre> 255</li> 256 257<li><code>res/values-sw600dp/layout.xml</code>: 258<pre> 259<resources> 260 <item name="main" type="layout">@layout/main_twopanes</item> 261</resources> 262</pre> 263 264</li> 265</ul></p> 266 267<p>These latter two files have identical content, but they don’t actually define 268the layout. They merely set up {@code main} to be an alias to {@code main_twopanes}. Since 269these files have <code>large</code> and <code>sw600dp</code> selectors, they are 270applied to tablets and TVs regardless of Android version (pre-3.2 tablets and TVs match 271{@code large}, and post-3.2 will match <code>sw600dp</code>).</p> 272 273 274<h2 id="TaskUseOriQuali">Use Orientation Qualifiers</h2> 275 276<p>Some layouts work well in both landscape and portrait orientations, but most of them can 277benefit from adjustments. In the News Reader sample app, here is how the layout 278behaves in each screen size and orientation:</p> 279 280<p><ul> 281<li><b>small screen, portrait:</b> single pane, with logo</li> 282<li><b>small screen, landscape:</b> single pane, with logo</li> 283<li><b>7" tablet, portrait:</b> single pane, with action bar</li> 284<li><b>7" tablet, landscape:</b> dual pane, wide, with action bar</li> 285<li><b>10" tablet, portrait:</b> dual pane, narrow, with action bar</li> 286<li><b>10" tablet, landscape:</b> dual pane, wide, with action bar</li> 287<li><b>TV, landscape:</b> dual pane, wide, with action bar</li> 288</ul></p> 289 290<p>So each of these layouts is defined in an XML file in the 291<code>res/layout/</code> directory. To then assign each layout to the various screen 292configurations, the app uses layout aliases to match them to 293each configuration:</p> 294 295<p><code>res/layout/onepane.xml:</code></p> 296{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all} 297 298<p><code>res/layout/onepane_with_bar.xml:</code></p> 299{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane_with_bar.xml all} 300 301<p><code>res/layout/twopanes.xml</code>:</p> 302{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} 303 304<p><code>res/layout/twopanes_narrow.xml</code>:</p> 305{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes_narrow.xml all} 306 307<p>Now that all possible layouts are defined, it's just a matter of mapping the correct layout to 308each configuration using the configuration qualifiers. You can now do it using the layout alias 309technique:</p> 310 311<p><code>res/values/layouts.xml</code>:</p> 312{@sample development/samples/training/multiscreen/newsreader/res/values/layouts.xml all} 313 314<p><code>res/values-sw600dp-land/layouts.xml</code>:</p> 315{@sample development/samples/training/multiscreen/newsreader/res/values-sw600dp-land/layouts.xml 316all} 317 318<p><code>res/values-sw600dp-port/layouts.xml</code>:</p> 319{@sample development/samples/training/multiscreen/newsreader/res/values-sw600dp-port/layouts.xml 320all} 321 322<p><code>res/values-large-land/layouts.xml</code>:</p> 323{@sample development/samples/training/multiscreen/newsreader/res/values-large-land/layouts.xml all} 324 325<p><code>res/values-large-port/layouts.xml</code>:</p> 326{@sample development/samples/training/multiscreen/newsreader/res/values-large-port/layouts.xml all} 327 328 329 330<h2 id="TaskUse9Patch">Use Nine-patch Bitmaps</h2> 331 332<p>Supporting different screen sizes usually means that your image resources 333must also be capable of adapting to different sizes. For example, a button 334background must fit whichever button shape it is applied to.</p> 335 336<p>If you use simple images on components that can change size, you will 337quickly notice that the results are somewhat less than impressive, since the 338runtime will stretch or shrink your images uniformly. The solution is using nine-patch bitmaps, 339which are specially 340formatted PNG files that indicate which areas can and cannot be stretched.</p> 341 342<p>Therefore, when designing bitmaps that will be used on components with 343variable size, always use nine-patches. To convert a bitmap into a nine-patch, 344you can start with a regular image (figure 4, shown with in 4x zoom for clarity).</p> 345 346<img src="{@docRoot}images/training/button.png" /> 347<p class="img-caption"><strong>Figure 4.</strong> <code>button.png</code></p> 348 349<p>And then run it through the <ode 350href="{@docRoot}tools/help/draw9patch.html"><code>draw9patch</code></a> utility of the 351SDK (which is located in the <code>tools/</code> directory), in which you can mark the areas that 352should be stretched by drawing pixels along the left and top borders. You can also mark the area 353that should hold the content by drawing pixels along the right and bottom borders, resulting in 354figure 5.</p> 355 356<img src="{@docRoot}images/training/button_with_marks.png" /> 357<p class="img-caption"><strong>Figure 5.</strong> <code>button.9.png</code></p> 358 359<p>Notice the black pixels along the borders. The ones on the top and left 360borders indicate the places where the image can be stretched, and the ones on 361the right and bottom borders indicate where the content should be 362placed.</p> 363 364<p>Also, notice the <code>.9.png</code> extension. You must use this 365extension, since this is how the framework detects that this is a nine-patch 366image, as opposed to a regular PNG image.</p> 367 368<p>When you apply this background to a component (by setting 369<code>android:background="@drawable/button"</code>), the framework stretches 370the image correctly to accommodate the size of the button, as shown in various sizes in figure 3716.</p> 372 373<img src="{@docRoot}images/training/buttons_stretched.png" /> 374<p class="img-caption"><strong>Figure 6.</strong> A button using the <code>button.9.png</code> 375nine-patch in various sizes.</p> 376 377