378 lines
16 KiB
Plaintext
378 lines
16 KiB
Plaintext
page.title=Supporting Different Screen Sizes
|
||
parent.title=Designing for Multiple Screens
|
||
parent.link=index.html
|
||
|
||
trainingnavtop=true
|
||
next.title=Supporting Different Screen Densities
|
||
next.link=screendensities.html
|
||
|
||
@jd:body
|
||
|
||
|
||
<!-- This is the training bar -->
|
||
<div id="tb-wrapper">
|
||
<div id="tb">
|
||
|
||
<h2>This lesson teaches you to</h2>
|
||
<ol>
|
||
<li><a href="#TaskUseWrapMatchPar">Use "wrap_content" and "match_parent"</a></li>
|
||
<li><a href="#TaskUseRelativeLayout">Use RelativeLayout</a></li>
|
||
<li><a href="#TaskUseSizeQuali">Use Size Qualifiers</a></li>
|
||
<li><a href="#TaskUseSWQuali">Use the Smallest-width Qualifier</a></li>
|
||
<li><a href="#TaskUseAliasFilters">Use Layout Aliases</a></li>
|
||
<li><a href="#TaskUseOriQuali">Use Orientation Qualifiers</a></li>
|
||
<li><a href="#TaskUse9Patch">Use Nine-patch Bitmaps</a></li>
|
||
</ol>
|
||
|
||
<h2>You should also read</h2>
|
||
|
||
<ul>
|
||
<li><a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a></li>
|
||
</ul>
|
||
|
||
<h2>Try it out</h2>
|
||
|
||
<div class="download-box">
|
||
<a href="http://developer.android.com/shareables/training/NewsReader.zip" class="button">Download
|
||
the sample app</a>
|
||
<p class="filename">NewsReader.zip</p>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<p>This lesson shows you how to support different screen sizes by:</p>
|
||
<ul>
|
||
<li>Ensuring your layout can be adequately resized to fit the screen</li>
|
||
<li>Providing appropriate UI layout according to screen configuration</li>
|
||
<li>Ensuring the correct layout is applied to the correct screen</li>
|
||
<li>Providing bitmaps that scale correctly</li>
|
||
</ul>
|
||
|
||
|
||
<h2 id="TaskUseWrapMatchPar">Use "wrap_content" and "match_parent"</h2>
|
||
|
||
<p>To ensure that your layout is flexible and adapts to different screen sizes,
|
||
you should use <code>"wrap_content"</code> and <code>"match_parent"</code> for the width
|
||
and height of some view components. If you use <code>"wrap_content"</code>, the width
|
||
or height of the view is set to the minimum size necessary to fit the content
|
||
within that view, while <code>"match_parent"</code> (also known as
|
||
<code>"fill_parent"</code> before API level 8) makes the component expand to match the size of its
|
||
parent view.</p>
|
||
|
||
<p>By using the <code>"wrap_content"</code> and <code>"match_parent"</code> size values instead of
|
||
hard-coded sizes, your views either use only the space required for that
|
||
view or expand to fill the available space, respectively. For example:</p>
|
||
|
||
{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane_with_bar.xml all}
|
||
|
||
<p>Notice how the sample uses <code>"wrap_content"</code> and <code>"match_parent"</code>
|
||
for component sizes rather than specific dimensions. This allows the layout
|
||
to adapt correctly to different screen sizes and orientations.</p>
|
||
|
||
<p>For example, this is what this layout looks like in portrait and landscape
|
||
mode. Notice that the sizes of the components adapt automatically to the
|
||
width and height:</p>
|
||
|
||
<img src="{@docRoot}images/training/layout-hvga.png" />
|
||
<p class="img-caption"><strong>Figure 1.</strong> The News Reader sample app in portrait (left)
|
||
and landscape (right).</p>
|
||
|
||
|
||
<h2 id="TaskUseRelativeLayout">Use RelativeLayout</h2>
|
||
|
||
<p>You can construct fairly complex layouts using nested instances of {@link
|
||
android.widget.LinearLayout} and
|
||
combinations of <code>"wrap_content"</code> and <code>"match_parent"</code> sizes.
|
||
However, {@link android.widget.LinearLayout} does not allow you to precisely control the
|
||
spacial relationships of child views; views in a {@link android.widget.LinearLayout} simply line up
|
||
side-by-side. If you need child views to be oriented in variations other than a straight line, a
|
||
better solution is often to use a {@link android.widget.RelativeLayout}, which allows
|
||
you to specify your layout in terms of the spacial relationships between
|
||
components. For instance, you can align one child view on the left side and another view on
|
||
the right side of the screen.</p>
|
||
|
||
<p>For example:</p>
|
||
|
||
<pre>
|
||
<?xml version="1.0" encoding="utf-8"?>
|
||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||
android:layout_width="match_parent"
|
||
android:layout_height="match_parent">
|
||
<TextView
|
||
android:id="@+id/label"
|
||
android:layout_width="match_parent"
|
||
android:layout_height="wrap_content"
|
||
android:text="Type here:"/>
|
||
<EditText
|
||
android:id="@+id/entry"
|
||
android:layout_width="match_parent"
|
||
android:layout_height="wrap_content"
|
||
android:layout_below="@id/label"/>
|
||
<Button
|
||
android:id="@+id/ok"
|
||
android:layout_width="wrap_content"
|
||
android:layout_height="wrap_content"
|
||
android:layout_below="@id/entry"
|
||
android:layout_alignParentRight="true"
|
||
android:layout_marginLeft="10dp"
|
||
android:text="OK" />
|
||
<Button
|
||
android:layout_width="wrap_content"
|
||
android:layout_height="wrap_content"
|
||
android:layout_toLeftOf="@id/ok"
|
||
android:layout_alignTop="@id/ok"
|
||
android:text="Cancel" />
|
||
</RelativeLayout>
|
||
</pre>
|
||
|
||
<p>Figure 2 shows how this layout appears on a QVGA screen.</p>
|
||
|
||
<img src="{@docRoot}images/training/relativelayout1.png" />
|
||
<p class="img-caption"><strong>Figure 2.</strong> Screenshot on a QVGA screen (small screen).</p>
|
||
|
||
<p>Figure 3 shows how it appears on a larger screen.</p>
|
||
|
||
<img src="{@docRoot}images/training/relativelayout2.png" />
|
||
<p class="img-caption"><strong>Figure 3.</strong> Screenshot on a WSVGA screen (large screen).</p>
|
||
|
||
<p>Notice that although the size of the components changed, their
|
||
spatial relationships are preserved as specified by the {@link
|
||
android.widget.RelativeLayout.LayoutParams}.</p>
|
||
|
||
|
||
<h2 id="TaskUseSizeQuali">Use Size Qualifiers</h2>
|
||
|
||
<p>There's only so much mileage you can get from a flexible layout or relative layout
|
||
like the one in the previous sections. While those layouts adapt to
|
||
different screens by stretching the space within and around components, they
|
||
may not provide the best user experience for each screen size. Therefore, your
|
||
application should not only implement flexible layouts, but should also provide
|
||
several alternative layouts to target different screen configurations. You do
|
||
so by using <a href="http://developer.android.com/guide/practices/screens_support.html#qualifiers">configuration qualifiers</a>, which allows the runtime
|
||
to automatically select the appropriate resource based on the current device’s
|
||
configuration (such as a different layout design for different screen sizes).</p>
|
||
|
||
<p>For example, many applications implement the "two pane" pattern for large
|
||
screens (the app might show a list of items on one pane and the content on
|
||
another pane). Tablets and TVs are large enough for both panes to fit
|
||
simultaneously on screen, but phone screens have to show them separately. So,
|
||
to implement these layouts, you could have the following files:</p>
|
||
|
||
<ul>
|
||
<li><code>res/layout/main.xml</code>, single-pane (default) layout:
|
||
|
||
{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all}
|
||
</li>
|
||
<li><code>res/layout-large/main.xml</code>, two-pane layout:
|
||
|
||
{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all}
|
||
</li>
|
||
</ul>
|
||
|
||
<p>Notice the <code>large</code> qualifier in the directory name of the second layout. This layout
|
||
will be selected on devices with screens classified as large (for example, 7" tablets and above). The
|
||
other layout (without qualifiers) will be selected for smaller devices.</p>
|
||
|
||
|
||
<h2 id="TaskUseSWQuali">Use the Smallest-width Qualifier</h2>
|
||
|
||
<p>One of the difficulties developers had in pre-3.2 Android devices was the
|
||
"large" screen size bin, which encompasses the Dell Streak, the original Galaxy
|
||
Tab, and 7" tablets in general. However, many applications may want to show
|
||
different layouts for different devices in this category (such as for 5" and 7" devices), even
|
||
though they are all considered to be "large" screens. That's why Android introduced the
|
||
"Smallest-width" qualifier (amongst others) in Android 3.2.</p>
|
||
|
||
<p>The Smallest-width qualifier allows you to target screens that have a certain minimum
|
||
width given in dp. For example, the typical 7" tablet has a minimum width of
|
||
600 dp, so if you want your UI to have two panes on those screens (but a single
|
||
list on smaller screens), you can use the same two layouts from the previous section for single
|
||
and two-pane layouts, but instead of the <code>large</code> size qualifier, use
|
||
<code>sw600dp</code> to indicate the two-pane layout is for screens on which the smallest-width
|
||
is 600 dp:</p>
|
||
|
||
<ul>
|
||
<li><code>res/layout/main.xml</code>, single-pane (default) layout:
|
||
|
||
{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all}
|
||
</li>
|
||
<li><code>res/layout-sw600dp/main.xml</code>, two-pane layout:
|
||
|
||
{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all}
|
||
</li>
|
||
</ul>
|
||
|
||
<p>This means that devices whose smallest width is greater than or equal to
|
||
600dp will select the <code>layout-sw600dp/main.xml</code> (two-pane) layout,
|
||
while smaller screens will select the <code>layout/main.xml</code> (single-pane)
|
||
layout.</p>
|
||
|
||
<p>However, this won't work well on pre-3.2 devices, because they don't
|
||
recognize <code>sw600dp</code> as a size qualifier, so you still have to use the <code>large</code>
|
||
qualifier as well. So, you should have a file named
|
||
<code>res/layout-large/main.xml</code>
|
||
which is identical to <code>res/layout-sw600dp/main.xml</code>. In the next section
|
||
you'll see a technique that allows you to avoid duplicating the layout files this way.</p>
|
||
|
||
|
||
<h2 id="TaskUseAliasFilters">Use Layout Aliases</h2>
|
||
|
||
<p>The smallest-width qualifier is available only on Android 3.2 and above.
|
||
Therefore, you should also still use the abstract size bins (small, normal,
|
||
large and xlarge) to be compatible with earlier versions. For example, if you
|
||
want to design your UI so that it shows a single-pane UI on phones but a
|
||
multi-pane UI on 7" tablets, TVs and other large devices, you'd have to supply these
|
||
files:</p>
|
||
|
||
<p><ul>
|
||
<li><code>res/layout/main.xml:</code> single-pane layout</li>
|
||
<li><code>res/layout-large:</code> multi-pane layout</li>
|
||
<li><code>res/layout-sw600dp:</code> multi-pane layout</li>
|
||
</ul></p>
|
||
|
||
<p>The last two files are identical, because one of them will be matched by
|
||
Android 3.2 devices, and the other one is for the benefit of tablets and TVs with
|
||
earlier versions of Android.</p>
|
||
|
||
<p>To avoid this duplication of the same file for tablets and TVs (and the maintenance
|
||
headache resulting from it), you can use alias files. For example, you can define the following
|
||
layouts:</p>
|
||
|
||
<ul>
|
||
<li><code>res/layout/main.xml</code>, single-pane layout</li>
|
||
<li><code>res/layout/main_twopanes.xml</code>, two-pane layout</li>
|
||
</ul>
|
||
|
||
<p>And add these two files:</p>
|
||
|
||
<p><ul>
|
||
<li><code>res/values-large/layout.xml</code>:
|
||
<pre>
|
||
<resources>
|
||
<item name="main" type="layout">@layout/main_twopanes</item>
|
||
</resources>
|
||
</pre>
|
||
</li>
|
||
|
||
<li><code>res/values-sw600dp/layout.xml</code>:
|
||
<pre>
|
||
<resources>
|
||
<item name="main" type="layout">@layout/main_twopanes</item>
|
||
</resources>
|
||
</pre>
|
||
|
||
</li>
|
||
</ul></p>
|
||
|
||
<p>These latter two files have identical content, but they don’t actually define
|
||
the layout. They merely set up {@code main} to be an alias to {@code main_twopanes}. Since
|
||
these files have <code>large</code> and <code>sw600dp</code> selectors, they are
|
||
applied to tablets and TVs regardless of Android version (pre-3.2 tablets and TVs match
|
||
{@code large}, and post-3.2 will match <code>sw600dp</code>).</p>
|
||
|
||
|
||
<h2 id="TaskUseOriQuali">Use Orientation Qualifiers</h2>
|
||
|
||
<p>Some layouts work well in both landscape and portrait orientations, but most of them can
|
||
benefit from adjustments. In the News Reader sample app, here is how the layout
|
||
behaves in each screen size and orientation:</p>
|
||
|
||
<p><ul>
|
||
<li><b>small screen, portrait:</b> single pane, with logo</li>
|
||
<li><b>small screen, landscape:</b> single pane, with logo</li>
|
||
<li><b>7" tablet, portrait:</b> single pane, with action bar</li>
|
||
<li><b>7" tablet, landscape:</b> dual pane, wide, with action bar</li>
|
||
<li><b>10" tablet, portrait:</b> dual pane, narrow, with action bar</li>
|
||
<li><b>10" tablet, landscape:</b> dual pane, wide, with action bar</li>
|
||
<li><b>TV, landscape:</b> dual pane, wide, with action bar</li>
|
||
</ul></p>
|
||
|
||
<p>So each of these layouts is defined in an XML file in the
|
||
<code>res/layout/</code> directory. To then assign each layout to the various screen
|
||
configurations, the app uses layout aliases to match them to
|
||
each configuration:</p>
|
||
|
||
<p><code>res/layout/onepane.xml:</code></p>
|
||
{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all}
|
||
|
||
<p><code>res/layout/onepane_with_bar.xml:</code></p>
|
||
{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane_with_bar.xml all}
|
||
|
||
<p><code>res/layout/twopanes.xml</code>:</p>
|
||
{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all}
|
||
|
||
<p><code>res/layout/twopanes_narrow.xml</code>:</p>
|
||
{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes_narrow.xml all}
|
||
|
||
<p>Now that all possible layouts are defined, it's just a matter of mapping the correct layout to
|
||
each configuration using the configuration qualifiers. You can now do it using the layout alias
|
||
technique:</p>
|
||
|
||
<p><code>res/values/layouts.xml</code>:</p>
|
||
{@sample development/samples/training/multiscreen/newsreader/res/values/layouts.xml all}
|
||
|
||
<p><code>res/values-sw600dp-land/layouts.xml</code>:</p>
|
||
{@sample development/samples/training/multiscreen/newsreader/res/values-sw600dp-land/layouts.xml
|
||
all}
|
||
|
||
<p><code>res/values-sw600dp-port/layouts.xml</code>:</p>
|
||
{@sample development/samples/training/multiscreen/newsreader/res/values-sw600dp-port/layouts.xml
|
||
all}
|
||
|
||
<p><code>res/values-large-land/layouts.xml</code>:</p>
|
||
{@sample development/samples/training/multiscreen/newsreader/res/values-large-land/layouts.xml all}
|
||
|
||
<p><code>res/values-large-port/layouts.xml</code>:</p>
|
||
{@sample development/samples/training/multiscreen/newsreader/res/values-large-port/layouts.xml all}
|
||
|
||
|
||
|
||
<h2 id="TaskUse9Patch">Use Nine-patch Bitmaps</h2>
|
||
|
||
<p>Supporting different screen sizes usually means that your image resources
|
||
must also be capable of adapting to different sizes. For example, a button
|
||
background must fit whichever button shape it is applied to.</p>
|
||
|
||
<p>If you use simple images on components that can change size, you will
|
||
quickly notice that the results are somewhat less than impressive, since the
|
||
runtime will stretch or shrink your images uniformly. The solution is using nine-patch bitmaps,
|
||
which are specially
|
||
formatted PNG files that indicate which areas can and cannot be stretched.</p>
|
||
|
||
<p>Therefore, when designing bitmaps that will be used on components with
|
||
variable size, always use nine-patches. To convert a bitmap into a nine-patch,
|
||
you can start with a regular image (figure 4, shown with in 4x zoom for clarity).</p>
|
||
|
||
<img src="{@docRoot}images/training/button.png" />
|
||
<p class="img-caption"><strong>Figure 4.</strong> <code>button.png</code></p>
|
||
|
||
<p>And then run it through the <ode
|
||
href="{@docRoot}tools/help/draw9patch.html"><code>draw9patch</code></a> utility of the
|
||
SDK (which is located in the <code>tools/</code> directory), in which you can mark the areas that
|
||
should be stretched by drawing pixels along the left and top borders. You can also mark the area
|
||
that should hold the content by drawing pixels along the right and bottom borders, resulting in
|
||
figure 5.</p>
|
||
|
||
<img src="{@docRoot}images/training/button_with_marks.png" />
|
||
<p class="img-caption"><strong>Figure 5.</strong> <code>button.9.png</code></p>
|
||
|
||
<p>Notice the black pixels along the borders. The ones on the top and left
|
||
borders indicate the places where the image can be stretched, and the ones on
|
||
the right and bottom borders indicate where the content should be
|
||
placed.</p>
|
||
|
||
<p>Also, notice the <code>.9.png</code> extension. You must use this
|
||
extension, since this is how the framework detects that this is a nine-patch
|
||
image, as opposed to a regular PNG image.</p>
|
||
|
||
<p>When you apply this background to a component (by setting
|
||
<code>android:background="@drawable/button"</code>), the framework stretches
|
||
the image correctly to accommodate the size of the button, as shown in various sizes in figure
|
||
6.</p>
|
||
|
||
<img src="{@docRoot}images/training/buttons_stretched.png" />
|
||
<p class="img-caption"><strong>Figure 6.</strong> A button using the <code>button.9.png</code>
|
||
nine-patch in various sizes.</p>
|
||
|