diff options
22 files changed, 1018 insertions, 53 deletions
diff --git a/Android.mk b/Android.mk index 85a4a7cf2072..742c9b26fd9c 100644 --- a/Android.mk +++ b/Android.mk @@ -432,6 +432,8 @@ web_docs_sample_code_flags := \ resources/samples/MultiResolution "Multiple Resolutions" \ -samplecode $(sample_dir)/NFCDemo \ resources/samples/NFCDemo "NFC Demo" \ + -samplecode $(sample_dir)/training/multiscreen/newsreader \ + resources/samples/newsreader "News Reader" \ -samplecode $(sample_dir)/NotePad \ resources/samples/NotePad "Note Pad" \ -samplecode $(sample_dir)/SpellChecker/SampleSpellCheckerService \ diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java index 5ae65df9826a..121c6f2f9324 100644 --- a/core/java/android/text/format/Formatter.java +++ b/core/java/android/text/format/Formatter.java @@ -21,7 +21,7 @@ import android.net.NetworkUtils; /** * Utility class to aid in formatting common values that are not covered - * by {@link java.util.Formatter} + * by the {@link java.util.Formatter} class in {@link java.util} */ public final class Formatter { diff --git a/core/java/android/text/format/package.html b/core/java/android/text/format/package.html new file mode 100644 index 000000000000..b9e6a44f60e0 --- /dev/null +++ b/core/java/android/text/format/package.html @@ -0,0 +1,7 @@ +<HTML> +<BODY> +This package contains alternative classes for some text formatting classes +defined in {@link java.util} and {@link java.text}. It also contains additional text formatting +classes for situations not covered by {@link java.util} or {@link java.text}. +</BODY> +</HTML> diff --git a/docs/html/images/training/button.png b/docs/html/images/training/button.png Binary files differnew file mode 100755 index 000000000000..1a7944fc4c9e --- /dev/null +++ b/docs/html/images/training/button.png diff --git a/docs/html/images/training/button_with_marks.png b/docs/html/images/training/button_with_marks.png Binary files differnew file mode 100755 index 000000000000..06e0720a805d --- /dev/null +++ b/docs/html/images/training/button_with_marks.png diff --git a/docs/html/images/training/buttons_stretched.png b/docs/html/images/training/buttons_stretched.png Binary files differnew file mode 100755 index 000000000000..bb6741997622 --- /dev/null +++ b/docs/html/images/training/buttons_stretched.png diff --git a/docs/html/images/training/layout-hvga.png b/docs/html/images/training/layout-hvga.png Binary files differnew file mode 100644 index 000000000000..b3403007ab89 --- /dev/null +++ b/docs/html/images/training/layout-hvga.png diff --git a/docs/html/images/training/relativelayout1.png b/docs/html/images/training/relativelayout1.png Binary files differnew file mode 100644 index 000000000000..0b593dcde930 --- /dev/null +++ b/docs/html/images/training/relativelayout1.png diff --git a/docs/html/images/training/relativelayout2.png b/docs/html/images/training/relativelayout2.png Binary files differnew file mode 100644 index 000000000000..341b286524af --- /dev/null +++ b/docs/html/images/training/relativelayout2.png diff --git a/docs/html/resources/resources-data.js b/docs/html/resources/resources-data.js index 18f1547d0ed9..d96bfde7add7 100644 --- a/docs/html/resources/resources-data.js +++ b/docs/html/resources/resources-data.js @@ -558,6 +558,16 @@ var ANDROID_RESOURCES = [ } }, { + tags: ['sample', 'new', 'bestpractices'], + path: 'samples/newsreader/index.html', + title: { + en: 'News Reader' + }, + description: { + en: 'A sample app demonstrating best practices to support multiple screen sizes and densities.' + } + }, + { tags: ['sample', 'data'], path: 'samples/NFCDemo/index.html', title: { diff --git a/docs/html/resources/samples/images/NewsReader.png b/docs/html/resources/samples/images/NewsReader.png Binary files differnew file mode 100644 index 000000000000..f44c6494f09d --- /dev/null +++ b/docs/html/resources/samples/images/NewsReader.png diff --git a/docs/html/sdk/android-4.0.jd b/docs/html/sdk/android-4.0.jd index e886bdf9ff74..7161b03708b5 100644 --- a/docs/html/sdk/android-4.0.jd +++ b/docs/html/sdk/android-4.0.jd @@ -65,26 +65,42 @@ experience possible on the latest Android-powered devices.</p> <p>To determine what revision of the Android {@sdkPlatformVersion} platform you have installed, refer to the "Installed Packages" listing in the Android SDK Manager.</p> +<p class="caution"><strong>Important:</strong> To download the new Android +4.0 system components from the Android SDK Manager, you must first update the +SDK tools to revision 14 or later and restart the Android SDK Manager. If you do not, +the Android 4.0 system components will not be available for download.</p> <div class="toggle-content opened" style="padding-left:1em;"> <p><a href="#" onclick="return toggleContent(this)"> <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img" alt="" /> - Android {@sdkPlatformVersion}, Revision 1</a> <em>(October 2011)</em> + Android {@sdkPlatformVersion}, Revision 2</a> <em>(December 2011)</em> </a></p> <div class="toggle-content-toggleme" style="padding-left:2em;"> + <p>Maintenance update. The system version is 4.0.2.</p> + <dl> + <dt>Dependencies:</dt> + <dd>SDK Tools r14 or higher is required.</dd> + </dl> + </div> +</div> -<dl> -<dt>Initial release. SDK Tools r14 or higher is required. - <p class="caution"><strong>Important:</strong> To download the new Android - 4.0 system components from the Android SDK Manager, you must first update the - SDK tools to revision 14 or later and restart the Android SDK Manager. If you do not, - the Android 4.0 system components will not be available for download.</p> -</dt> -</dl> +<div class="toggle-content closed" style="padding-left:1em;"> + <p><a href="#" onclick="return toggleContent(this)"> + <img src="{@docRoot}assets/images/triangle-closed.png" +class="toggle-content-img" alt="" /> + Android {@sdkPlatformVersion}, Revision 1</a> <em>(October 2011)</em> + </a></p> + + <div class="toggle-content-toggleme" style="padding-left:2em;"> + <p>Initial release. The system version is 4.0.1.</p> + <dl> + <dt>Dependencies:</dt> + <dd>SDK Tools r14 or higher is required.</dd> + </dl> </div> </div> diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd index 50b20cea9e64..2445bffa92a2 100644 --- a/docs/html/sdk/eclipse-adt.jd +++ b/docs/html/sdk/eclipse-adt.jd @@ -1,8 +1,8 @@ page.title=ADT Plugin for Eclipse -adt.zip.version=15.0.1 -adt.zip.download=ADT-15.0.1.zip -adt.zip.bytes=6752327 -adt.zip.checksum=2c12a71d7124aa512b8ee016e19c0e69 +adt.zip.version=16.0.0 +adt.zip.download=ADT-16.0.0.zip +adt.zip.bytes=6999205 +adt.zip.checksum=b7e512572580291279469845386b31b6 @jd:body @@ -109,18 +109,49 @@ padding: .25em 1em; </style> - <div class="toggleable opened"> <a href="#" onclick="return toggleDiv(this)"> <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px" /> +ADT 16.0.0</a> <em>(December 2011)</em> + <div class="toggleme"> +<dl> + <dt>Dependencies:</dt> + + <dd> + <ul> + <li>Eclipse Helios (Version 3.6) or higher is required for ADT +16.0.0.</li> + <li>ADT 16.0.0 is designed for use with <a +href="{@docRoot}sdk/tools-notes.html">SDK Tools r16</a>. If you haven't already installed SDK Tools +r16 into your SDK, use the Android SDK Manager to do so.</li> + </ul> + </dd> + + <dt>General improvements:</dt> + <dd> + <ul> + <li>Added Lint tools to detect common errors in Android projects. (<a +href="http://tools.android.com/recent/lint">more info</a>)</li> + </ul> + </dd> +</dl> + +</div> +</div> + + +<div class="toggleable closed"> + <a href="#" onclick="return toggleDiv(this)"> + <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px" +width="9px" /> ADT 15.0.1</a> <em>(November 2011)</em> <div class="toggleme"> <dl> <dt>Dependencies:</dt> <dd>ADT 15.0.1 is designed for use with <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r15</a>. - If you haven't already installed SDK Tools r15 into your SDK, use the Android SDK and AVD Manager to + If you haven't already installed SDK Tools r15 into your SDK, use the Android SDK Manager to do so.</dd> <dt>Bug fixes:</dt> @@ -154,7 +185,7 @@ ADT 15.0.0</a> <em>(October 2011)</em> <dt>Dependencies:</dt> <dd>ADT 15.0.0 is designed for use with <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r15</a>. -If you haven't already installed SDK Tools r15 into your SDK, use the Android SDK and AVD Manager to +If you haven't already installed SDK Tools r15 into your SDK, use the Android SDK Manager to do so.</dd> <dt>Bug fixes:</dt> @@ -185,10 +216,10 @@ ADT 14.0.0</a> <em>(October 2011)</em> <dt>Dependencies:</dt> <dd>ADT 14.0.0 is designed for use with <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r14</a>. -If you haven't already installed SDK Tools r14 into your SDK, use the Android SDK and AVD Manager to +If you haven't already installed SDK Tools r14 into your SDK, use the Android SDK Manager to do so.</dd> -<dt>Build system</dt> +<dt>Build system:</dt> <dd> <ul> <li>Changed <code>default.properties</code> to <code>project.properties</code> and @@ -211,7 +242,7 @@ see the <a href="http://tools.android.com/recent/buildchangesinrevision14">Andro site</a>.</p> </dd> -<dt>General improvements</dt> +<dt>General improvements:</dt> <dd> <ul> @@ -236,7 +267,7 @@ and deleted without affecting the master copy </ul> </dd> -<dt>XML and Java editors</dt> +<dt>XML and Java editors:</dt> <dd> <ul> <li>Added a new XML formatter that formats all XML files according to the @@ -255,7 +286,7 @@ href="http://tools.android.com/recent/xmleditingimprovements">more info</a>).</l </ul> </dd> -<dt>Layout editor</dt> +<dt>Layout editor:</dt> <dd> <ul> <li>Added tooltip feedback for dragging and resizing operations. For @@ -281,7 +312,7 @@ href="http://tools.android.com/recent/layouteditorcontextmenuimprovements">more </ul> </dd> -<dt>Bug fixes</dt> +<dt>Bug fixes:</dt> <dd>Fixed many bugs and added <a href="http://tools.android.com/recent/miscellaneousrecentfixes">minor improvements</a>, in particular some <a href="http://tools.android.com/recent/linuxfixes">critical bug fixes on @@ -324,7 +355,7 @@ the Android SDK and AVD Manager to do so.</dd> </ul> </dd> -<dt>Build system</dt> +<dt>Build system:</dt> <dd> <ul> <li id="build-option">A new option lets you disable the packaging step in the automatic @@ -336,7 +367,7 @@ the Android SDK and AVD Manager to do so.</dd> </ul> </dd> -<dt>Bug fixes</dt> +<dt>Bug fixes:</dt> <dd>Many bug fixes are part of this release (<a href="http://tools.android.com/recent/adt12bugfixroundup">more info</a>).</dd> @@ -928,7 +959,7 @@ Manager to download the latest SDK Tools into your SDK. For more information, see <a href="{@docRoot}sdk/adding-components.html">Adding SDK Components</a>.</p> </dd> -<dt>General Notes:</dt> +<dt>General notes:</dt> <dd> <ul> <li>AVD Launch dialog now shows scale value.</li> @@ -974,7 +1005,7 @@ bigger than the screen.</li> </ul> </dd> -<dt>DDMS Integration:</dt> +<dt>DDMS integration:</dt> <dd> <ul> <li>Includes the improvements from the standlone DDMS, revision 3.</li> diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd index 193066bab310..65a1f465c475 100644 --- a/docs/html/sdk/index.jd +++ b/docs/html/sdk/index.jd @@ -1,21 +1,21 @@ page.title=Android SDK sdk.redirect=0 -sdk.win_installer=installer_r15-windows.exe -sdk.win_installer_bytes=33902520 -sdk.win_installer_checksum=ee8481cb86a6646a4d963d5142902c5c +sdk.win_installer=installer_r16-windows.exe +sdk.win_installer_bytes=29561554 +sdk.win_installer_checksum=3521dda4904886b05980590f83cf3469 -sdk.win_download=android-sdk_r15-windows.zip -sdk.win_bytes=33895447 -sdk.win_checksum=cc2aadf7120d12b574981461736a96e9 +sdk.win_download=android-sdk_r16-windows.zip +sdk.win_bytes=29562413 +sdk.win_checksum=6b926d0c0a871f1a946e65259984701a -sdk.mac_download=android-sdk_r15-macosx.zip -sdk.mac_bytes=30469921 -sdk.mac_checksum=03d2cdd3565771e8c7a438f1c40cc8a5 +sdk.mac_download=android-sdk_r16-macosx.zip +sdk.mac_bytes=26158334 +sdk.mac_checksum=d1dc2b6f13eed5e3ce5cf26c4e4c47aa -sdk.linux_download=android-sdk_r15-linux.tgz -sdk.linux_bytes=26124434 -sdk.linux_checksum=f529681fd1eda11c6e1e1d44b42c1432 +sdk.linux_download=android-sdk_r16-linux.tgz +sdk.linux_bytes=22048174 +sdk.linux_checksum=3ba457f731d51da3741c29c8830a4583 @jd:body diff --git a/docs/html/sdk/requirements.jd b/docs/html/sdk/requirements.jd index f12d0aa68ed9..c970f6c9c0be 100644 --- a/docs/html/sdk/requirements.jd +++ b/docs/html/sdk/requirements.jd @@ -24,8 +24,8 @@ Android applications using the Android SDK. </p> <h4 style="margin-top:.25em"><em>Eclipse IDE</em></h4> <ul> - <li>Eclipse 3.5 (Galileo) or greater -<p class="note"><strong>Note:</strong> Eclipse 3.4 (Ganymede) is no longer + <li>Eclipse 3.6 (Helios) or greater +<p class="note"><strong>Note:</strong> Eclipse 3.5 (Galileo) is no longer supported with the latest version of ADT.</p></li> <li>Eclipse <a href="http://www.eclipse.org/jdt">JDT</a> plugin (included in most Eclipse IDE packages) </li> @@ -37,7 +37,7 @@ developing Android applications, we recommend that you install one of these packages: </p> <ul> <li>Eclipse IDE for Java Developers</li> - <li>Eclipse Classic (versions 3.5.1 and higher)</li> + <li>Eclipse Classic</li> <li>Eclipse IDE for Java EE Developers</li> </ul> </li> diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs index 0ae2c6dba37b..791e7aa201f7 100644 --- a/docs/html/sdk/sdk_toc.cs +++ b/docs/html/sdk/sdk_toc.cs @@ -150,7 +150,7 @@ class="new">new!</span></li> </li> </ul> <ul> - <li><a href="<?cs var:toroot ?>sdk/tools-notes.html">SDK Tools, r15</a> <span + <li><a href="<?cs var:toroot ?>sdk/tools-notes.html">SDK Tools, r16</a> <span class="new">new!</span></li> <li><a href="<?cs var:toroot ?>sdk/win-usb.html">Google USB Driver, r4</a></li> <li><a href="<?cs var:toroot ?>sdk/compatibility-library.html">Support Package, r4</a> @@ -169,7 +169,7 @@ class="new">new!</span></li> <span style="display:none" class="zh-TW"></span> </h2> <ul> - <li><a href="<?cs var:toroot ?>sdk/eclipse-adt.html">ADT 15.0.1 + <li><a href="<?cs var:toroot ?>sdk/eclipse-adt.html">ADT 16.0.0 <span style="display:none" class="de"></span> <span style="display:none" class="es"></span> <span style="display:none" class="fr"></span> diff --git a/docs/html/sdk/tools-notes.jd b/docs/html/sdk/tools-notes.jd index cd03d9fa800d..9a63467274cb 100644 --- a/docs/html/sdk/tools-notes.jd +++ b/docs/html/sdk/tools-notes.jd @@ -9,7 +9,7 @@ href="{@docRoot}sdk/index.html">SDK starter package</a> installs the latest revision of the SDK Tools in the <code><sdk>/tools</code> directory.</p> <p>If you are already using the SDK and you want to update to the latest version -of the SDK Tools, use the <em>Android SDK and AVD Manager</em> to get the +of the SDK Tools, use the <em>Android SDK Manager</em> to get the update, rather than downloading a new SDK starter package. For more information about how to update, see <a href="{@docRoot}sdk/adding-components.html#UpdatingComponents">Updating SDK @@ -20,8 +20,7 @@ Components</a>.</p> <p>The sections below provide notes about successive releases of the SDK Tools, as denoted by revision number. To determine what revision of the SDK -Tools you are using, refer to the "Installed Packages" listing in the Android SDK -and AVD Manager. </p> +Tools you are using, refer to the "Installed Packages" listing in the Android SDK Manager. </p> <p>For a summary of all known issues in SDK Tools, see <a href="http://tools.android.com/knownissues">http://tools.android.com/knownissues</a>.</p> @@ -69,7 +68,57 @@ padding: .25em 1em; <div class="toggleable opened"> <a href="#" onclick="return toggleDiv(this)"> <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" - width="9px" />SDK Tools, Revision 15</a> <em>(October 2011)</em> + width="9px" /> + SDK Tools, Revision 16</a> <em>(December 2011)</em> + + <div class="toggleme"> + <p class="caution"><strong>Important:</strong> To download the new Android + 4.0 system components from the Android SDK Manager, you must first update the + SDK tools to revision 14 or later and restart the Android SDK Manager. If you do not, + the Android 4.0 system components will not be available for download.</p> + +<dl> +<dt>Dependencies:</dt> +<dd> + <ul> + <li>Android SDK Platform-tools revision 9 or later.</li> + <li>If you are developing in Eclipse with ADT, note that the SDK Tools r16 is designed for use + with ADT 16.0.0 and later. If you haven't already, we highly recommend updating your + <a href="{@docRoot}sdk/eclipse-adt.html">ADT Plugin</a> to 16.0.0.</li> + <li>If you are developing outside Eclipse, you must have <a href="http://ant.apache.org/">Apache + Ant</a> 1.8 or later.</li> +</ul> +</dd> +<dt>General notes:</dt> +<dd> + <ul> + <li>Added Lint tools to detect common errors in Android projects. (<a +href="http://tools.android.com/recent/lint">more info</a>)</li> + <li>Added sensor emulation support, which allows the emulator to read sensor data from a +physical Android device.</li> + <li>Added support for using a webcam to emulate a camera on Mac OS X.</li> + </ul> +</dd> +<dt>Bug fixes:</dt> +<dd> + <ul> + <li>Snapshots now work for Android 4.0 system images.</li> + <li>Fixed several small issues for the build file. + (<a href="http://code.google.com/p/android/issues/detail?id=21023">Issue 21023</a>, + <a href="http://code.google.com/p/android/issues/detail?id=21267">Issue 21267</a>, + <a href="http://code.google.com/p/android/issues/detail?id=21465">Issue 21465</a>, + <a href="http://code.google.com/p/android/issues/detail?id=21525">Issue 21525</a>).</li> + </ul> +</dd> +</dl> +</div> +</div> + +<div class="toggleable closed"> + <a href="#" onclick="return toggleDiv(this)"> + <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px" + width="9px" /> + SDK Tools, Revision 15</a> <em>(October 2011)</em> <div class="toggleme"> <p class="caution"><strong>Important:</strong> To download the new Android @@ -116,7 +165,8 @@ padding: .25em 1em; <div class="toggleable closed"> <a href="#" onclick="return toggleDiv(this)"> <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px" - width="9px" />SDK Tools, Revision 14</a> <em>(October 2011)</em> + width="9px" /> + SDK Tools, Revision 14</a> <em>(October 2011)</em> <div class="toggleme"> <p class="note"><strong>Important:</strong> To download the new Android @@ -137,10 +187,11 @@ padding: .25em 1em; <dt>General notes:</dt> <dd> <ul> - <li>Added webcam support to Android 4.0 or later platforms to emulate rear-facing cameras when one webcam is present, - and to emulate both rear-facing and front-facing cameras when two webcams are present. Webcam suport is for Windows and Linux only. + <li>Added webcam support to Android 4.0 or later platforms to emulate rear-facing cameras when + one webcam is present, and to emulate both rear-facing and front-facing cameras when two + webcams are present. Webcam support is for Windows and Linux only. Mac support will come in a later release.</li> - <li>Changed <code>default.properties</code> to <code>project.properties</code> and + <li>Changed <code>default.properties</code> to <code>project.properties</code> and <code>build.properties</code> to <code>ant.properties</code>. Any existing projects that you build with Ant must be updated with the <code>android update project</code> command.</li> @@ -428,7 +479,7 @@ normal tasks: <code>-pre-build</code>, <code>-pre-compile</code>, and for more information.</li> <li>Fixes location control in DDMS to work in any locale not using '.' as a decimal point.</li> -</li> +</ul> </ul> </dd> </dl> diff --git a/docs/html/shareables/training/NewsReader.zip b/docs/html/shareables/training/NewsReader.zip Binary files differnew file mode 100644 index 000000000000..7dda41c7c273 --- /dev/null +++ b/docs/html/shareables/training/NewsReader.zip diff --git a/docs/html/training/multiscreen/adaptui.jd b/docs/html/training/multiscreen/adaptui.jd new file mode 100644 index 000000000000..34e9d7df7f8d --- /dev/null +++ b/docs/html/training/multiscreen/adaptui.jd @@ -0,0 +1,258 @@ +page.title=Implementing Adaptative UI Flows +parent.title=Designing for Multiple Screens +parent.link=index.html + +trainingnavtop=true +previous.title=Supporting Different Screen Densities +previous.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="#TaskDetermineCurLayout">Determine the Current Layout</a></li> + <li><a href="#TaskReactToLayout">React According to Current Layout</a></li> + <li><a href="#TaskReuseFrag">Reuse Fragments in Other Activities</a></li> + <li><a href="#TaskHandleConfigChanges">Handle Screen Configuration Changes</a></li> +</ol> + +<h2>You should also read</h2> + +<ul> + <li><a href="{@docRoot}guide/practices/tablets-and-handsets.html">Supporting Tablets and +Handsets</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>Depending on the layout that your application is currently showing, the UI +flow may be different. For example, if your application is in the dual-pane +mode, clicking on an item on the left pane will simply display the content on +the right pane; if it is in single-pane mode, the content should be displayed +on its own (in a different activity).</p> + + +<h2 id="TaskDetermineCurLayout">Determine the Current Layout</h2> + +<p>Since your implementation of each layout will be a little different, one of +the first things you will probably have to do is determine what layout the user is currently +viewing. For example, you might want to know whether the user is in "single +pane" mode or "dual pane" mode. You can do that by querying if a given view +exists and is visible:</p> + +<pre class="prettyprint"> +public class NewsReaderActivity extends FragmentActivity { + boolean mIsDualPane; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main_layout); + + View articleView = findViewById(R.id.article); + mIsDualPane = articleView != null && + articleView.getVisibility() == View.VISIBLE; + } +} +</pre> + +<p>Notice that this code queries whether the "article" pane is available or not, +which is much more flexible than hard-coding a query for a specific layout.</p> + +<p>Another example of how you can adapt to the existence of different +components is to check whether they are available before performing an operation on +them. For example, in the News Reader sample app, there is a button that opens a +menu, but that button only exists when running on versions older than Android 3.0 (because it's +function is taken over by the {@link android.app.ActionBar} on API level 11+). So, to add the event +listener for this button, you can do:</p> + +<pre class="prettyprint"> +Button catButton = (Button) findViewById(R.id.categorybutton); +OnClickListener listener = /* create your listener here */; +if (catButton != null) { + catButton.setOnClickListener(listener); +} +</pre> + + +<h2 id="TaskReactToLayout">React According to Current Layout</h2> + +<p>Some actions may have a different result depending on the current layout. +For example, in the News Reader sample, clicking on a headline from the +headlines list opens the article in the right hand-side pane if the UI +is in dual pane mode, but will launch a separate activity if the UI is in +single-pane mode:</p> + +<pre> +@Override +public void onHeadlineSelected(int index) { + mArtIndex = index; + if (mIsDualPane) { + /* display article on the right pane */ + mArticleFragment.displayArticle(mCurrentCat.getArticle(index)); + } else { + /* start a separate activity */ + Intent intent = new Intent(this, ArticleActivity.class); + intent.putExtra("catIndex", mCatIndex); + intent.putExtra("artIndex", index); + startActivity(intent); + } +} +</pre> + +<p>Likewise, if the app is in dual-pane mode, it should set up the action bar +with tabs for navigation, whereas if the app is in single-pane mode, it should set +up navigation with a spinner widget. So your code should also check which case is +appropriate:</p> + +<pre> +final String CATEGORIES[] = { "Top Stories", "Politics", "Economy", "Technology" }; + +public void onCreate(Bundle savedInstanceState) { + .... + if (mIsDualPane) { + /* use tabs for navigation */ + actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_TABS); + int i; + for (i = 0; i < CATEGORIES.length; i++) { + actionBar.addTab(actionBar.newTab().setText( + CATEGORIES[i]).setTabListener(handler)); + } + actionBar.setSelectedNavigationItem(selTab); + } + else { + /* use list navigation (spinner) */ + actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_LIST); + SpinnerAdapter adap = new ArrayAdapter<String>(this, + R.layout.headline_item, CATEGORIES); + actionBar.setListNavigationCallbacks(adap, handler); + } +} +</pre> + + +<h2 id="TaskReuseFrag">Reuse Fragments in Other Activities</h2> + +<p>A recurring pattern in designing for multiple screens is having a portion of +your interface that's implemented as a pane on some screen configurations and +as a separate activity on other configurations. For example, in the News Reader +sample, the news article text is presented in the right side pane on +large screens, but is a separate activity on smaller screens.</p> + +<p>In cases like this, you can usually avoid code duplication by reusing the +same {@link android.app.Fragment} subclass in several activities. For example, +<code>ArticleFragment</code> +is used in the dual-pane layout:</p> + +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} + +<p>And reused (without a layout) in the activity layout for smaller screens +(<code>ArticleActivity</code>):</p> + +<pre> +ArticleFragment frag = new ArticleFragment(); +getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag).commit(); +</pre> + +<p>Naturally, this has the same effect as declaring the fragment in an XML +layout, but in this case an XML layout is unnecessary work because the article fragment +is the only component of this activity.</p> + +<p>One very important point to keep in mind when designing your fragments is +to not create a strong coupling to a specific activity. You can usually do that +by defining an interface that abstracts all the ways in which the fragment +needs to interact with its host activity, and then the host activity +implements that interface:</p> + +<p>For example, the News Reader app's <code>HeadlinesFragment</code> does precisely that:</p> + +<pre> +public class HeadlinesFragment extends ListFragment { + ... + OnHeadlineSelectedListener mHeadlineSelectedListener = null; + + /* Must be implemented by host activity */ + public interface OnHeadlineSelectedListener { + public void onHeadlineSelected(int index); + } + ... + + public void setOnHeadlineSelectedListener(OnHeadlineSelectedListener listener) { + mHeadlineSelectedListener = listener; + } +} +</pre> + +<p>Then, when the user selects a headline, the fragment notifies the listener specified by the host +activity (as opposed to notifying a specific hard-coded activity):</p> + +<pre> +public class HeadlinesFragment extends ListFragment { + ... + @Override + public void onItemClick(AdapterView<?> parent, + View view, int position, long id) { + if (null != mHeadlineSelectedListener) { + mHeadlineSelectedListener.onHeadlineSelected(position); + } + } + ... +} +</pre> + +<p>This technique is discussed further in the guide to <a +href="{@docRoot}guide/practices/tablets-and-handsets.html">Supporting Tablets and Handsets</a>.</p> + + +<h2 id="TaskHandleConfigChanges">Handle Screen Configuration Changes</h2> + +<p>If you are using separate activities to implement separate parts of your interface, +you have to keep in mind that it may be necessary to react to certain +configuration changes (such as a rotation change) in order to keep your +interface consistent.</p> + +<p>For example, on a typical 7" tablet running Android 3.0 or higher, the News Reader sample uses a +separate activity to display the news article when running in portrait mode, +but uses a two-pane layout when in landscape mode.</p> + +<p>This means that when the user is in portrait mode and the activity for viewing an article is +onscreen, you need to detect that the orientation changed to landscape and +react appropriately by ending the activity and return to the main activity so the content can +display in the two-pane layout:</p> + +<pre> +public class ArticleActivity extends FragmentActivity { + int mCatIndex, mArtIndex; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mCatIndex = getIntent().getExtras().getInt("catIndex", 0); + mArtIndex = getIntent().getExtras().getInt("artIndex", 0); + + // If should be in two-pane mode, finish to return to main activity + if (getResources().getBoolean(R.bool.has_two_panes)) { + finish(); + return; + } + ... +} +</pre> + + diff --git a/docs/html/training/multiscreen/index.jd b/docs/html/training/multiscreen/index.jd new file mode 100644 index 000000000000..a986cef18804 --- /dev/null +++ b/docs/html/training/multiscreen/index.jd @@ -0,0 +1,87 @@ +page.title=Designing for Multiple Screens + +trainingnavtop=true +startpage=true +next.title=Supporting Different Screen Sizes +next.link=screensizes.html + +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> + +<h2>Dependencies and prerequisites</h2> + +<ul> + <li>Android 1.6 or higher (2.1+ for the sample app)</li> + <li>Basic knowledge of <a +href="http://developer.android.com/guide/topics/fundamentals/activities.html">Activities</a> and +<a href="http://developer.android.com/guide/topics/fundamentals/fragments.html">Fragments</a></li> + <li>Experience building an Android <a +href="http://developer.android.com/guide/topics/ui/index.html"> User Interface</a></li> + <li>Several features require the use of the <a +href="{@docRoot}sdk/compatibility-library.html">support library</a></li> +</ul> + +<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>Android powers hundreds of device types with several different screen sizes, +ranging from small phones to large TV sets. Therefore, it’s important +that you design your application to be compatible with all screen sizes so it’s available to as many +users as possible.</p> + +<p>But being compatible with different device types is not enough. Each screen +size offers different possibilities and challenges for user interaction, so in +order to truly satisfy and impress your users, your application must go beyond merely +<em>supporting</em> multiple screens: it must <em>optimize</em> the user +experience for each screen configuration.</p> + +<p>This class shows you how to implement a user interface that's +optimized for several screen configurations.</p> + +<p>The code in each lesson comes from a sample application that demonstrates best practices in +optimizing for multiple screens. You can download the sample (to the right) and use it as a source +of reusable code for your own application.</p> + +<p class="note"><strong>Note:</strong> This class and the associated sample use the <a +href="{@docRoot}sdk/compatibility-library.html">support library</a> in order to use the {@link +android.app.Fragment} APIs on versions lower than Android 3.0. You must download and add the +library to your application in order to use all APIs in this class.</p> + + +<h2>Lessons</h2> + +<dl> + <dt><b><a href="screensizes.html">Supporting Different Screen Sizes</a></b></dt> + <dd>This lesson walks you through how to design layouts that adapts + several different screen sizes (using flexible dimensions for + views, {@link android.widget.RelativeLayout}, screen size and orientation qualifiers, + alias filters, and nine-patch bitmaps).</dd> + + <dt><b><a href="screendensities.html">Supporting Different Screen + Densities</a></b></dt> + <dd>This lesson shows you how to support screens that have different + pixel densities (using density-independent pixels and providing + bitmaps appropriate for each density).</dd> + + <dt><b><a href="adaptui.html">Implementing Adaptative UI Flows</a></b></dt> + <dd>This lesson shows you how to implement your UI flow in a way + that adapts to several screen size/density combinations + (run-time detection of active layout, reacting according to + current layout, handling screen configuration changes).</dd> +</dl> diff --git a/docs/html/training/multiscreen/screendensities.jd b/docs/html/training/multiscreen/screendensities.jd new file mode 100644 index 000000000000..7d6ff4486f1d --- /dev/null +++ b/docs/html/training/multiscreen/screendensities.jd @@ -0,0 +1,127 @@ +page.title=Supporting Different Densities +parent.title=Designing for Multiple Screens +parent.link=index.html + +trainingnavtop=true +previous.title=Supporting Different Screen Sizes +previous.link=screensizes.html +next.title=Implementing Adaptative UI Flows +next.link=adaptui.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="#TaskUseDP">Use Density-independent Pixels</a></li> + <li><a href="#TaskProvideAltBmp">Provide Alternative 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> + <li><a href="{@docRoot}guide/practices/ui_guidelines/icon_design.html">Icon Design +Guidelines</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 densities +by providing different resources and using resolution-independent units of +measurements.</p> + +<h2 id="TaskUseDP">Use Density-independent Pixels</h2> + +<p>One common pitfall you must avoid when designing your layouts is using +absolute pixels to define distances or sizes. Defining layout dimensions with +pixels is a problem because different screens have different pixel densities, +so the same number of pixels may correspond to different physical sizes on +different devices. Therefore, when specifying dimensions, always use either +<code>dp</code> or <code>sp</code> units. A <code>dp</code> is a density-independent pixel +that corresponds to the physical size of a pixel at 160 dpi. An <code>sp</code> is the same +base unit, but is scaled by the user's preferred text size (it’s a +scale-independent pixel), so you should use this measurement unit when defining +text size (but never for layout sizes).</p> + +<p>For example, when you specify spacing between two views, use <code>dp</code> +rather than <code>px</code>:</p> + +<pre> +<Button android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/clickme" + android:layout_marginTop="20dp" /> +</pre> + +<p>When specifying text size, always use <code>sp</code>:</p> + +<pre> +<TextView android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textSize="20sp" /> +</pre> + + +<h2 id="TaskProvideAltBmp">Provide Alternative Bitmaps</h2> + +<p>Since Android runs in devices with a wide variety of screen densities, +you should always provide your bitmap resources tailored to each of +the generalized density buckets: low, medium, high and extra-high density. +This will help you achieve good graphical quality and performance on all +screen densities.</p> + +<p>To generate these images, you should start with your raw resource in +vector format and generate the images for each density using the following +size scale:</p> + +<p><ul> + <li><code>xhdpi</code>: 2.0 + <li><code>hdpi</code>: 1.5 + <li><code>mdpi</code>: 1.0 (baseline) + <li><code>ldpi</code>: 0.75 +</ul></p> + +<p>This means that if you generate a 200x200 image for <code>xhdpi</code> +devices, you should generate the same resource in 150x150 for <code>hdpi</code>, +100x100 for <code>mdpi</code> and finally a 75x75 image for <code>ldpi</code> +devices.</p> + +<p>Then, place the generated image files in the appropriate subdirectory +under <code>res/</code> and the system will pick the correct one automatically +based on the screen density of the device your application is running on:</p> + +<pre class="classic no-pretty-print"> +MyProject/ + res/ + drawable-xhdpi/ + awesomeimage.png + drawable-hdpi/ + awesomeimage.png + drawable-mdpi/ + awesomeimage.png + drawable-ldpi/ + awesomeimage.png +</pre> + +<p>Then, any time you reference <code>@drawable/awesomeimage</code>, the system selects the +appropriate bitmap based on the screen's dpi.</p> + +<p>For more tips and guidelines for creating icon assets for your application, see the <a +href="{@docRoot}guide/practices/ui_guidelines/icon_design.html">Icon Design +Guidelines</a>.</p> + diff --git a/docs/html/training/multiscreen/screensizes.jd b/docs/html/training/multiscreen/screensizes.jd new file mode 100644 index 000000000000..2db0b67bb922 --- /dev/null +++ b/docs/html/training/multiscreen/screensizes.jd @@ -0,0 +1,376 @@ +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-xlarge/main.xml</code>, two-pane layout: + +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} +</li> +</ul> + +<p>Notice the <code>xlarge</code> qualifier in the directory name of the second layout. This layout +will be selected on devices with screens classified as extra-large (for example, 10" tablets). 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>xlarge</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>xlarge</code> +qualifier as well. So, you should have a file named +<code>res/layout-xlarge/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 and larger 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-xlarge:</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 with +earlier versions of Android.</p> + +<p>To avoid this duplication of the same file for tablets (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-xlarge/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>xlarge</code> and <code>sw600dp</code> selectors, they are +applied to tablets regardless of Android version (pre-3.2 tablets match +{@code xlarge}, 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> +</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-xlarge-land/layouts.xml</code>:</p> +{@sample development/samples/training/multiscreen/newsreader/res/values-xlarge-land/layouts.xml all} + +<p><code>res/values-xlarge-port/layouts.xml</code>:</p> +{@sample development/samples/training/multiscreen/newsreader/res/values-xlarge-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}guide/developing/tools/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> + |