blob: 2db0b67bb9223ad6a4ddfabc199608abff4f39ef [file] [log] [blame]
Scott Main801fda52011-12-09 17:27:21 -08001page.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> (also known as
60<code>"fill_parent"</code> before API level 8) makes the component expand to match the size of its
61parent view.</p>
62
63<p>By using the <code>"wrap_content"</code> and <code>"match_parent"</code> size values instead of
64hard-coded sizes, your views either use only the space required for that
65view or expand to fill the available space, respectively. For example:</p>
66
67{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane_with_bar.xml all}
68
69<p>Notice how the sample uses <code>"wrap_content"</code> and <code>"match_parent"</code>
70for component sizes rather than specific dimensions. This allows the layout
71to adapt correctly to different screen sizes and orientations.</p>
72
73<p>For example, this is what this layout looks like in portrait and landscape
74mode. Notice that the sizes of the components adapt automatically to the
75width and height:</p>
76
77<img src="{@docRoot}images/training/layout-hvga.png" />
78<p class="img-caption"><strong>Figure 1.</strong> The News Reader sample app in portrait (left)
79and landscape (right).</p>
80
81
82<h2 id="TaskUseRelativeLayout">Use RelativeLayout</h2>
83
84<p>You can construct fairly complex layouts using nested instances of {@link
85android.widget.LinearLayout} and
86combinations of <code>"wrap_content"</code> and <code>"match_parent"</code> sizes.
87However, {@link android.widget.LinearLayout} does not allow you to precisely control the
88spacial relationships of child views; views in a {@link android.widget.LinearLayout} simply line up
89side-by-side. If you need child views to be oriented in variations other than a straight line, a
90better solution is often to use a {@link android.widget.RelativeLayout}, which allows
91you to specify your layout in terms of the spacial relationships between
92components. For instance, you can align one child view on the left side and another view on
93the right side of the screen.</p>
94
95<p>For example:</p>
96
97<pre>
98&lt;?xml version="1.0" encoding="utf-8"?&gt;
99&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
100 android:layout_width="match_parent"
101 android:layout_height="match_parent"&gt;
102 &lt;TextView
103 android:id="&#64;+id/label"
104 android:layout_width="match_parent"
105 android:layout_height="wrap_content"
106 android:text="Type here:"/&gt;
107 &lt;EditText
108 android:id="&#64;+id/entry"
109 android:layout_width="match_parent"
110 android:layout_height="wrap_content"
111 android:layout_below="&#64;id/label"/&gt;
112 &lt;Button
113 android:id="&#64;+id/ok"
114 android:layout_width="wrap_content"
115 android:layout_height="wrap_content"
116 android:layout_below="&#64;id/entry"
117 android:layout_alignParentRight="true"
118 android:layout_marginLeft="10dp"
119 android:text="OK" /&gt;
120 &lt;Button
121 android:layout_width="wrap_content"
122 android:layout_height="wrap_content"
123 android:layout_toLeftOf="&#64;id/ok"
124 android:layout_alignTop="&#64;id/ok"
125 android:text="Cancel" /&gt;
126&lt;/RelativeLayout&gt;
127</pre>
128
129<p>Figure 2 shows how this layout appears on a QVGA screen.</p>
130
131<img src="{@docRoot}images/training/relativelayout1.png" />
132<p class="img-caption"><strong>Figure 2.</strong> Screenshot on a QVGA screen (small screen).</p>
133
134<p>Figure 3 shows how it appears on a larger screen.</p>
135
136<img src="{@docRoot}images/training/relativelayout2.png" />
137<p class="img-caption"><strong>Figure 3.</strong> Screenshot on a WSVGA screen (large screen).</p>
138
139<p>Notice that although the size of the components changed, their
140spatial relationships are preserved as specified by the {@link
141android.widget.RelativeLayout.LayoutParams}.</p>
142
143
144<h2 id="TaskUseSizeQuali">Use Size Qualifiers</h2>
145
146<p>There's only so much mileage you can get from a flexible layout or relative layout
147like the one in the previous sections. While those layouts adapt to
148different screens by stretching the space within and around components, they
149may not provide the best user experience for each screen size. Therefore, your
150application should not only implement flexible layouts, but should also provide
151several alternative layouts to target different screen configurations. You do
152so by using <a href="http://developer.android.com/guide/practices/screens_support.html#qualifiers">configuration qualifiers</a>, which allows the runtime
153to automatically select the appropriate resource based on the current device’s
154configuration (such as a different layout design for different screen sizes).</p>
155
156<p>For example, many applications implement the "two pane" pattern for large
157screens (the app might show a list of items on one pane and the content on
158another pane). Tablets and TVs are large enough for both panes to fit
159simultaneously on screen, but phone screens have to show them separately. So,
160to implement these layouts, you could have the following files:</p>
161
162<ul>
163 <li><code>res/layout/main.xml</code>, single-pane (default) layout:
164
165{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all}
166</li>
167 <li><code>res/layout-xlarge/main.xml</code>, two-pane layout:
168
169{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all}
170</li>
171</ul>
172
173<p>Notice the <code>xlarge</code> qualifier in the directory name of the second layout. This layout
174will be selected on devices with screens classified as extra-large (for example, 10" tablets). The
175other layout (without qualifiers) will be selected for smaller devices.</p>
176
177
178<h2 id="TaskUseSWQuali">Use the Smallest-width Qualifier</h2>
179
180<p>One of the difficulties developers had in pre-3.2 Android devices was the
181"large" screen size bin, which encompasses the Dell Streak, the original Galaxy
182Tab, and 7" tablets in general. However, many applications may want to show
183different layouts for different devices in this category (such as for 5" and 7" devices), even
184though they are all considered to be "large" screens. That's why Android introduced the
185"Smallest-width" qualifier (amongst others) in Android 3.2.</p>
186
187<p>The Smallest-width qualifier allows you to target screens that have a certain minimum
188width given in dp. For example, the typical 7" tablet has a minimum width of
189600 dp, so if you want your UI to have two panes on those screens (but a single
190list on smaller screens), you can use the same two layouts from the previous section for single
191and two-pane layouts, but instead of the <code>xlarge</code> size qualifier, use
192<code>sw600dp</code> to indicate the two-pane layout is for screens on which the smallest-width
193is 600 dp:</p>
194
195<ul>
196 <li><code>res/layout/main.xml</code>, single-pane (default) layout:
197
198{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all}
199</li>
200 <li><code>res/layout-sw600dp/main.xml</code>, two-pane layout:
201
202{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all}
203</li>
204</ul>
205
206<p>This means that devices whose smallest width is greater than or equal to
207600dp will select the <code>layout-sw600dp/main.xml</code> (two-pane) layout,
208while smaller screens will select the <code>layout/main.xml</code> (single-pane)
209layout.</p>
210
211<p>However, this won't work well on pre-3.2 devices, because they don't
212recognize <code>sw600dp</code> as a size qualifier, so you still have to use the <code>xlarge</code>
213qualifier as well. So, you should have a file named
214<code>res/layout-xlarge/main.xml</code>
215which is identical to <code>res/layout-sw600dp/main.xml</code>. In the next section
216you'll see a technique that allows you to avoid duplicating the layout files this way.</p>
217
218
219<h2 id="TaskUseAliasFilters">Use Layout Aliases</h2>
220
221<p>The smallest-width qualifier is available only on Android 3.2 and above.
222Therefore, you should also still use the abstract size bins (small, normal,
223large and xlarge) to be compatible with earlier versions. For example, if you
224want to design your UI so that it shows a single-pane UI on phones but a
225multi-pane UI on 7" tablets and larger devices, you'd have to supply these
226files:</p>
227
228<p><ul>
229<li><code>res/layout/main.xml:</code> single-pane layout</li>
230<li><code>res/layout-xlarge:</code> multi-pane layout</li>
231<li><code>res/layout-sw600dp:</code> multi-pane layout</li>
232</ul></p>
233
234<p>The last two files are identical, because one of them will be matched by
235Android 3.2 devices, and the other one is for the benefit of tablets with
236earlier versions of Android.</p>
237
238<p>To avoid this duplication of the same file for tablets (and the maintenance
239headache resulting from it), you can use alias files. For example, you can define the following
240layouts:</p>
241
242<ul>
243<li><code>res/layout/main.xml</code>, single-pane layout</li>
244<li><code>res/layout/main_twopanes.xml</code>, two-pane layout</li>
245</ul>
246
247<p>And add these two files:</p>
248
249<p><ul>
250<li><code>res/values-xlarge/layout.xml</code>:
251<pre>
252&lt;resources>
253 &lt;item name="main" type="layout">&#64;layout/main_twopanes&lt;/item>
254&lt;/resources>
255</pre>
256</li>
257
258<li><code>res/values-sw600dp/layout.xml</code>:
259<pre>
260&lt;resources>
261 &lt;item name="main" type="layout">&#64;layout/main_twopanes&lt;/item>
262&lt;/resources>
263</pre>
264
265</li>
266</ul></p>
267
268<p>These latter two files have identical content, but they don’t actually define
269the layout. They merely set up {@code main} to be an alias to {@code main_twopanes}. Since
270these files have <code>xlarge</code> and <code>sw600dp</code> selectors, they are
271applied to tablets regardless of Android version (pre-3.2 tablets match
272{@code xlarge}, and post-3.2 will match <code>sw600dp</code>).</p>
273
274
275<h2 id="TaskUseOriQuali">Use Orientation Qualifiers</h2>
276
277<p>Some layouts work well in both landscape and portrait orientations, but most of them can
278benefit from adjustments. In the News Reader sample app, here is how the layout
279behaves in each screen size and orientation:</p>
280
281<p><ul>
282<li><b>small screen, portrait:</b> single pane, with logo</li>
283<li><b>small screen, landscape:</b> single pane, with logo</li>
284<li><b>7" tablet, portrait:</b> single pane, with action bar</li>
285<li><b>7" tablet, landscape:</b> dual pane, wide, with action bar</li>
286<li><b>10" tablet, portrait:</b> dual pane, narrow, with action bar</li>
287<li><b>10" tablet, 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-xlarge-land/layouts.xml</code>:</p>
323{@sample development/samples/training/multiscreen/newsreader/res/values-xlarge-land/layouts.xml all}
324
325<p><code>res/values-xlarge-port/layouts.xml</code>:</p>
326{@sample development/samples/training/multiscreen/newsreader/res/values-xlarge-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}guide/developing/tools/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="&#64;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