diff options
author | Roman Nurik <romannurik@google.com> | 2012-04-13 17:53:17 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2012-04-13 17:53:17 -0700 |
commit | 4d7038cb96690c93c6ca407d338159ea062424fb (patch) | |
tree | 3d77cc8612188d45be9af5537de0418aa218f350 | |
parent | 509efe16a1e191ac8e65709feed20eaae2894343 (diff) | |
parent | 3fc245a181269c5e425698d8ad212015812ebd8d (diff) | |
download | frameworks_base-4d7038cb96690c93c6ca407d338159ea062424fb.zip frameworks_base-4d7038cb96690c93c6ca407d338159ea062424fb.tar.gz frameworks_base-4d7038cb96690c93c6ca407d338159ea062424fb.tar.bz2 |
am 3fc245a1: am 38e09c3d: docs: Android Training: Creating Backward-Compatible UIs class
* commit '3fc245a181269c5e425698d8ad212015812ebd8d':
docs: Android Training: Creating Backward-Compatible UIs class
-rw-r--r-- | docs/html/images/training/backward-compatible-ui-classes-eclair.png | bin | 0 -> 11962 bytes | |||
-rw-r--r-- | docs/html/images/training/backward-compatible-ui-classes-honeycomb.png | bin | 0 -> 13123 bytes | |||
-rw-r--r-- | docs/html/images/training/backward-compatible-ui-classes.png | bin | 0 -> 22677 bytes | |||
-rw-r--r-- | docs/html/images/training/backward-compatible-ui-gb.png | bin | 0 -> 17373 bytes | |||
-rw-r--r-- | docs/html/images/training/backward-compatible-ui-ics.png | bin | 0 -> 16147 bytes | |||
-rw-r--r-- | docs/html/resources/resources_toc.cs | 26 | ||||
-rw-r--r-- | docs/html/shareables/training/TabCompat.zip | bin | 0 -> 579116 bytes | |||
-rw-r--r-- | docs/html/training/backward-compatible-ui/abstracting.jd | 111 | ||||
-rw-r--r-- | docs/html/training/backward-compatible-ui/index.jd | 57 | ||||
-rw-r--r-- | docs/html/training/backward-compatible-ui/new-implementation.jd | 113 | ||||
-rw-r--r-- | docs/html/training/backward-compatible-ui/older-implementation.jd | 126 | ||||
-rw-r--r-- | docs/html/training/backward-compatible-ui/using-component.jd | 143 |
12 files changed, 575 insertions, 1 deletions
diff --git a/docs/html/images/training/backward-compatible-ui-classes-eclair.png b/docs/html/images/training/backward-compatible-ui-classes-eclair.png Binary files differnew file mode 100644 index 0000000..febba5b --- /dev/null +++ b/docs/html/images/training/backward-compatible-ui-classes-eclair.png diff --git a/docs/html/images/training/backward-compatible-ui-classes-honeycomb.png b/docs/html/images/training/backward-compatible-ui-classes-honeycomb.png Binary files differnew file mode 100644 index 0000000..ba14252 --- /dev/null +++ b/docs/html/images/training/backward-compatible-ui-classes-honeycomb.png diff --git a/docs/html/images/training/backward-compatible-ui-classes.png b/docs/html/images/training/backward-compatible-ui-classes.png Binary files differnew file mode 100644 index 0000000..c5a3cd8 --- /dev/null +++ b/docs/html/images/training/backward-compatible-ui-classes.png diff --git a/docs/html/images/training/backward-compatible-ui-gb.png b/docs/html/images/training/backward-compatible-ui-gb.png Binary files differnew file mode 100644 index 0000000..621ee63 --- /dev/null +++ b/docs/html/images/training/backward-compatible-ui-gb.png diff --git a/docs/html/images/training/backward-compatible-ui-ics.png b/docs/html/images/training/backward-compatible-ui-ics.png Binary files differnew file mode 100644 index 0000000..6460554 --- /dev/null +++ b/docs/html/images/training/backward-compatible-ui-ics.png diff --git a/docs/html/resources/resources_toc.cs b/docs/html/resources/resources_toc.cs index 6fe36fa..686bde3 100644 --- a/docs/html/resources/resources_toc.cs +++ b/docs/html/resources/resources_toc.cs @@ -227,7 +227,31 @@ class="new"> new!</span></span> </li> </ul> </li> - + + <li class="toggle-list"> + <div><a href="<?cs var:toroot ?>training/backward-compatible-ui/index.html"> + <span class="en">Creating Backward-Compatible UIs<span class="new"> new!</span></span> + </a></div> + <ul> + <li><a href="<?cs var:toroot ?>training/backward-compatible-ui/abstracting.html"> + <span class="en">Abstracting the New APIs</span> + </a> + </li> + <li><a href="<?cs var:toroot ?>training/backward-compatible-ui/new-implementation.html"> + <span class="en">Proxying to the New APIs</span> + </a> + </li> + <li><a href="<?cs var:toroot ?>training/backward-compatible-ui/older-implementation.html"> + <span class="en">Creating an Implementation with Older APIs</span> + </a> + </li> + <li><a href="<?cs var:toroot ?>training/backward-compatible-ui/using-component.html"> + <span class="en">Using the Version-Aware Component</span> + </a> + </li> + </ul> + </li> + <li class="toggle-list"> <div><a href="<?cs var:toroot ?>training/enterprise/index.html"> <span class="en">Developing for Enterprise</span> diff --git a/docs/html/shareables/training/TabCompat.zip b/docs/html/shareables/training/TabCompat.zip Binary files differnew file mode 100644 index 0000000..b70b442 --- /dev/null +++ b/docs/html/shareables/training/TabCompat.zip diff --git a/docs/html/training/backward-compatible-ui/abstracting.jd b/docs/html/training/backward-compatible-ui/abstracting.jd new file mode 100644 index 0000000..1141b54 --- /dev/null +++ b/docs/html/training/backward-compatible-ui/abstracting.jd @@ -0,0 +1,111 @@ +page.title=Abstracting the New APIs +parent.title=Creating Backward-Compatible UIs +parent.link=index.html + +trainingnavtop=true +next.title=Proxying to the New APIs +next.link=new-implementation.html + +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> + +<h2>This lesson teaches you to:</h2> +<ul> + <li><a href="#prepare-abstraction">Prepare for Abstraction</a></li> + <li><a href="#create-abstract-tab">Create an Abstract Tab Interface</a></li> + <li><a href="#abstract-actionbar-tab">Abstract ActionBar.Tab</a></li> + <li><a href="#abstract-actionbar-methods">Abstract ActionBar Tab Methods</a></li> +</ul> + +<h2>You should also read</h2> +<ul> + <li><a href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a></li> + <li><a href="{@docRoot}guide/topics/ui/actionbar.html#Tabs">Action Bar Tabs</a></li> +</ul> + +<h2>Try it out</h2> + +<div class="download-box"> +<a href="http://developer.android.com/shareables/training/TabCompat.zip" + class="button">Download the sample app</a> +<p class="filename">TabCompat.zip</p> +</div> + +</div> +</div> + +<p>Suppose you want to use <a href="{@docRoot}guide/topics/ui/actionbar.html#Tabs">action bar tabs</a> as the primary form of top-level navigation in your application. Unfortunately, the {@link android.app.ActionBar} APIs are only available in Android 3.0 or later (API level 11+). Thus, if you want to distribute your application to devices running earlier versions of the platform, you need to provide an implementation that supports the newer API while providing a fallback mechanism that uses older APIs.</p> + +<p>In this class, you build a tabbed user interface (UI) component that uses abstract classes with version-specific implementations to provide backward-compatibility. This lesson describes how to create an abstraction layer for the new tab APIs as the first step toward building the tab component.</p> + +<h2 id="prepare-abstraction">Prepare for Abstraction</h2> + +<p><a href="http://en.wikipedia.org/wiki/Abstraction_(computer_science)">Abstraction</a> in the Java programming language involves the creation of one or more interfaces or abstract classes to hide implementation details. In the case of newer Android APIs, you can use abstraction to build version-aware components that use the current APIs on newer devices, and fallback to older, more compatible APIs on older devices.</p> + +<p>When using this approach, you first determine what newer classes you want to be able to use in a backward compatible way, then create abstract classes, based on the public interfaces of the newer classes. In defining the abstraction interfaces, you should mirror the newer API as much as possible. This maximizes forward-compatibility and makes it easier to drop the abstraction layer in the future when it is no longer necessary.</p> + +<p>After creating abstract classes for these new APIs, any number of implementations can be created and chosen at runtime. For the purposes of backward-compatibility, these implementations can vary by required API level. Thus, one implementation may use recently released APIs, while others can use older APIs.</p> + +<h2 id="create-abstract-tab">Create an Abstract Tab Interface</h2> + +<p>In order to create a backward-compatible version of tabs, you should first determine which features and specific APIs your application requires. In the case of top-level section tabs, suppose you have the following functional requirements:</p> + +<ol> +<li>Tab indicators should show text and an icon.</li> +<li>Tabs can be associated with a fragment instance.</li> +<li>The activity should be able to listen for tab changes.</li> +</ol> + +<p>Preparing these requirements in advance allows you to control the scope of your abstraction layer. This means that you can spend less time creating multiple implementations of your abstraction layer and begin using your new backward-compatible implementation sooner.</p> + +<p>The key APIs for tabs are in {@link android.app.ActionBar} and {@link android.app.ActionBar.Tab ActionBar.Tab}. These are the APIs to abstract in order to make your tabs version-aware. The requirements for this example project call for compatibility back to Eclair (API level 5) while taking advantage of the new tab features in Honeycomb (API Level 11). A diagram of the class structure to support these two implementations and their abstract base classes (or interfaces) is shown below.</p> + +<img src="{@docRoot}images/training/backward-compatible-ui-classes.png" + alt="Class diagram of abstract base classes and version-specific implementations." id="figure-classes"> + +<p class="img-caption"><strong>Figure 1.</strong> Class diagram of abstract base classes and version-specific implementations.</p> + +<h2 id="abstract-actionbar-tab">Abstract ActionBar.Tab</h2> + +<p>Get started on building your tab abstraction layer by creating an abstract class representing a tab, that mirrors the {@link android.app.ActionBar.Tab ActionBar.Tab} interface:</p> + +<pre> +public abstract class CompatTab { + ... + public abstract CompatTab setText(int resId); + public abstract CompatTab setIcon(int resId); + public abstract CompatTab setTabListener( + CompatTabListener callback); + public abstract CompatTab setFragment(Fragment fragment); + + public abstract CharSequence getText(); + public abstract Drawable getIcon(); + public abstract CompatTabListener getCallback(); + public abstract Fragment getFragment(); + ... +} +</pre> + +<p>You can use an abstract class instead of an interface here to simplify the implementation of common features such as association of tab objects with activities (not shown in the code snippet).</p> + +<h2 id="abstract-actionbar-methods">Abstract ActionBar Tab Methods</h2> + +<p>Next, define an abstract class that allows you to create and add tabs to an activity, like {@link android.app.ActionBar#newTab ActionBar.newTab()} and {@link android.app.ActionBar#addTab ActionBar.addTab()}:</p> + +<pre> +public abstract class TabHelper { + ... + + public CompatTab newTab(String tag) { + // This method is implemented in a later lesson. + } + + public abstract void addTab(CompatTab tab); + + ... +} +</pre> + +<p>In the next lessons, you create implementations for <code>TabHelper</code> and <code>CompatTab</code> that work across both older and newer platform versions.</p> diff --git a/docs/html/training/backward-compatible-ui/index.jd b/docs/html/training/backward-compatible-ui/index.jd new file mode 100644 index 0000000..7e27e68 --- /dev/null +++ b/docs/html/training/backward-compatible-ui/index.jd @@ -0,0 +1,57 @@ +page.title=Creating Backward-Compatible UIs + +trainingnavtop=true +startpage=true +next.title=Abstracting the New Implementation +next.link=abstracting.html + +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> + +<h2>Dependencies and prerequisites</h2> + +<ul> + <li>API level 5</li> + <li><a href="{@docRoot}sdk/compatibility-library.html">The Android Support Package</a></li> +</ul> + +<h2>You should also read</h2> + +<ul> + <li><a href="{@docRoot}resources/samples/ActionBarCompat/index.html">ActionBarCompat</a></li> + <li><a href="http://android-developers.blogspot.com/2010/07/how-to-have-your-cupcake-and-eat-it-too.html">How to have your (Cup)cake and eat it too</a></li> +</ul> + +<h2>Try it out</h2> + +<div class="download-box"> +<a href="http://developer.android.com/shareables/training/TabCompat.zip" + class="button">Download the sample app</a> +<p class="filename">TabCompat.zip</p> +</div> + +</div> +</div> + +<p>This class demonstrates how to use UI components and APIs available in newer versions of Android in a backward-compatible way, ensuring that your application still runs on previous versions of the platform.</p> + +<p>Throughout this class, the new <a href="{@docRoot}guide/topics/ui/actionbar.html#Tabs">Action Bar Tabs</a> feature introduced in Android 3.0 (API level 11) serves as the guiding example, but you can apply these techniques to other UI components and API features.</p> + +<h2 id="lessons">Lessons</h2> + + +<dl> + <dt><strong><a href="abstracting.html">Abstracting the New APIs</a></strong></dt> + <dd>Determine which features and APIs your application needs. Learn how to define application-specific, intermediary Java interfaces that abstract the implementation of the UI component to your application.</dd> + + <dt><strong><a href="new-implementation.html">Proxying to the New APIs</a></strong></dt> + <dd>Learn how to create an implementation of your interface that uses newer APIs.</dd> + + <dt><strong><a href="older-implementation.html">Creating an Implementation with Older APIs</a></strong></dt> + <dd>Learn how to create a custom implementation of your interface that uses older APIs.</dd> + + <dt><strong><a href="using-component.html">Using the Version-Aware Component</a></strong></dt> + <dd>Learn how to choose an implementation to use at runtime, and begin using the interface in your application.</dd> +</dl> diff --git a/docs/html/training/backward-compatible-ui/new-implementation.jd b/docs/html/training/backward-compatible-ui/new-implementation.jd new file mode 100644 index 0000000..5b8b51c --- /dev/null +++ b/docs/html/training/backward-compatible-ui/new-implementation.jd @@ -0,0 +1,113 @@ +page.title=Proxying to the New APIs +parent.title=Creating Backward-Compatible UIs +parent.link=index.html + +trainingnavtop=true +previous.title=Abstracting the New APIs +previous.link=abstracting.html +next.title=Creating an Implementation with Older APIs +next.link=older-implementation.html + +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> + +<h2>This lesson teaches you to:</h2> +<ol> + <li><a href="#new-tabs">Implement Tabs Using New APIs</a></li> + <li><a href="#compattabhoneycomb">Implement CompatTabHoneycomb</a></li> + <li><a href="#tabhelperhoneycomb">Implement TabHelperHoneycomb</a></li> +</ol> + +<h2>You should also read</h2> +<ul> + <li><a href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a></li> + <li><a href="{@docRoot}guide/topics/ui/actionbar.html#Tabs">Action Bar Tabs</a></li> +</ul> + +<h2>Try it out</h2> + +<div class="download-box"> +<a href="http://developer.android.com/shareables/training/TabCompat.zip" + class="button">Download the sample app</a> +<p class="filename">TabCompat.zip</p> +</div> + +</div> +</div> + +<p>This lesson shows you how to subclass the <code>CompatTab</code> and <code>TabHelper</code> abstract classes and use new APIs. Your application can use this implementation on devices running a platform version that supports them.</p> + +<h2 id="new-tabs">Implement Tabs Using New APIs</h2> + +<p>The concrete classes for <code>CompatTab</code> and <code>TabHelper</code> that use newer APIs are a <em>proxy</em> implementation. Since the abstract classes defined in the previous lesson mirror the new APIs (class structure, method signatures, etc.), the concrete classes that use these newer APIs simply proxy method calls and their results.</p> + +<p>You can directly use newer APIs in these concrete classes—and not crash on earlier devices—because of lazy class loading. Classes are loaded and initialized on first access—instantiating the class or accessing one of its static fields or methods for the first time. Thus, as long as you don't instantiate the Honeycomb-specific implementations on pre-Honeycomb devices, the Dalvik VM won't throw any {@link java.lang.VerifyError} exceptions.</p> + +<p>A good naming convention for this implementation is to append the API level or platform version code name corresponding to the APIs required by the concrete classes. For example, the native tab implementation can be provided by <code>CompatTabHoneycomb</code> and <code>TabHelperHoneycomb</code> classes, since they rely on APIs available in Android 3.0 (API level 11) or later.</p> + +<img src="{@docRoot}images/training/backward-compatible-ui-classes-honeycomb.png" + alt="Class diagram for the Honeycomb implementation of tabs." id="figure-classes"> + +<p class="img-caption"><strong>Figure 1.</strong> Class diagram for the Honeycomb implementation of tabs.</p> + +<h2 id="compattabhoneycomb">Implement CompatTabHoneycomb</h2> + +<p><code>CompatTabHoneycomb</code> is the implementation of the <code>CompatTab</code> abstract class that <code>TabHelperHoneycomb</code> uses to reference individual tabs. <code>CompatTabHoneycomb</code> simply proxies all method calls to its contained {@link android.app.ActionBar.Tab} object.</p> + +<p>Begin implementing <code>CompatTabHoneycomb</code> using the new {@link android.app.ActionBar.Tab ActionBar.Tab} APIs:</p> + +<pre> +public class CompatTabHoneycomb extends CompatTab { + // The native tab object that this CompatTab acts as a proxy for. + ActionBar.Tab mTab; + ... + + protected CompatTabHoneycomb(FragmentActivity activity, String tag) { + ... + // Proxy to new ActionBar.newTab API + mTab = activity.getActionBar().newTab(); + } + + public CompatTab setText(int resId) { + // Proxy to new ActionBar.Tab.setText API + mTab.setText(resId); + return this; + } + + ... + // Do the same for other properties (icon, callback, etc.) +} +</pre> + +<h2 id="tabhelperhoneycomb">Implement TabHelperHoneycomb</h2> + +<p><code>TabHelperHoneycomb</code> is the implementation of the <code>TabHelper</code> abstract class that proxies method calls to an actual {@link android.app.ActionBar}, obtained from its contained {@link android.app.Activity}.</p> + +<p>Implement <code>TabHelperHoneycomb</code>, proxying method calls to the {@link android.app.ActionBar} API:</p> + +<pre> +public class TabHelperHoneycomb extends TabHelper { + ActionBar mActionBar; + ... + + protected void setUp() { + if (mActionBar == null) { + mActionBar = mActivity.getActionBar(); + mActionBar.setNavigationMode( + ActionBar.NAVIGATION_MODE_TABS); + } + } + + public void addTab(CompatTab tab) { + ... + // Tab is a CompatTabHoneycomb instance, so its + // native tab object is an ActionBar.Tab. + mActionBar.addTab((ActionBar.Tab) tab.getTab()); + } + + // The other important method, newTab() is part of + // the base implementation. +} +</pre>
\ No newline at end of file diff --git a/docs/html/training/backward-compatible-ui/older-implementation.jd b/docs/html/training/backward-compatible-ui/older-implementation.jd new file mode 100644 index 0000000..5006123 --- /dev/null +++ b/docs/html/training/backward-compatible-ui/older-implementation.jd @@ -0,0 +1,126 @@ +page.title=Creating an Implementation with Older APIs +parent.title=Creating Backward-Compatible UIs +parent.link=index.html + +trainingnavtop=true +previous.title=Proxying to the New APIs +previous.link=new-implementation.html +next.title=Using the Version-Aware Component +next.link=using-component.html + +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> + +<h2>This lesson teaches you to:</h2> +<ol> + <li><a href="#decide-substitute">Decide on a Substitute Solution</a></li> + <li><a href="#older-tabs">Implement Tabs Using Older APIs</a></li> +</ol> + +<h2>Try it out</h2> + +<div class="download-box"> +<a href="http://developer.android.com/shareables/training/TabCompat.zip" + class="button">Download the sample app</a> +<p class="filename">TabCompat.zip</p> +</div> + +</div> +</div> + + +<p>This lesson discusses how to create an implementation that mirrors newer APIs yet supports older devices.</p> + +<h2 id="decide-substitute">Decide on a Substitute Solution</h2> + +<p>The most challenging task in using newer UI features in a backward-compatible way is deciding on and implementing an older (fallback) solution for older platform versions. In many cases, it's possible to fulfill the purpose of these newer UI components using older UI framework features. For example:</p> + +<ul> + +<li> +<p>Action bars can be implemented using a horizontal {@link android.widget.LinearLayout} containing image buttons, either as custom title bars or as views in your activity layout. Overflow actions can be presented under the device <em>Menu</em> button.</p> +</li> + +<li> +<p>Action bar tabs can be implemented using a horizontal {@link android.widget.LinearLayout} containing buttons, or using the {@link android.widget.TabWidget} UI element.</p> +</li> + +<li> +<p>{@link android.widget.NumberPicker} and {@link android.widget.Switch} widgets can be implemented using {@link android.widget.Spinner} and {@link android.widget.ToggleButton} widgets, respectively.</p> +</li> + +<li> +<p>{@link android.widget.ListPopupWindow} and {@link android.widget.PopupMenu} widgets can be implemented using {@link android.widget.PopupWindow} widgets.</p> +</li> + +</ul> + +<p>There generally isn't a one-size-fits-all solution for backporting newer UI components to older devices. Be mindful of the user experience: on older devices, users may not be familiar with newer design patterns and UI components. Give some thought as to how the same functionality can be delivered using familiar elements. In many cases this is less of a concern—if newer UI components are prominent in the application ecosystem (such as the action bar), or where the interaction model is extremely simple and intuitive (such as swipe views using a {@link android.support.v4.view.ViewPager}).</p> + +<h2 id="older-tabs">Implement Tabs Using Older APIs</h2> + +<p>To create an older implementation of action bar tabs, you can use a {@link android.widget.TabWidget} and {@link android.widget.TabHost} (although one can alternatively use horizontally laid-out {@link android.widget.Button} widgets). Implement this in classes called <code>TabHelperEclair</code> and <code>CompatTabEclair</code>, since this implementation uses APIs introduced no later than Android 2.0 (Eclair).</p> + + +<img src="{@docRoot}images/training/backward-compatible-ui-classes-eclair.png" + alt="Class diagram for the Eclair implementation of tabs." id="figure-classes"> + +<p class="img-caption"><strong>Figure 1.</strong> Class diagram for the Eclair implementation of tabs.</p> + +<p>The <code>CompatTabEclair</code> implementation stores tab properties such as the tab text and icon in instance variables, since there isn't an {@link android.app.ActionBar.Tab ActionBar.Tab} object available to handle this storage:</p> + +<pre> +public class CompatTabEclair extends CompatTab { + // Store these properties in the instance, + // as there is no ActionBar.Tab object. + private CharSequence mText; + ... + + public CompatTab setText(int resId) { + // Our older implementation simply stores this + // information in the object instance. + mText = mActivity.getResources().getText(resId); + return this; + } + + ... + // Do the same for other properties (icon, callback, etc.) +} +</pre> + +<p>The <code>TabHelperEclair</code> implementation makes use of methods on the +{@link android.widget.TabHost} widget for creating {@link android.widget.TabHost.TabSpec} +objects and tab indicators:</p> + +<pre> +public class TabHelperEclair extends TabHelper { + private TabHost mTabHost; + ... + + protected void setUp() { + if (mTabHost == null) { + // Our activity layout for pre-Honeycomb devices + // must contain a TabHost. + mTabHost = (TabHost) mActivity.findViewById( + android.R.id.tabhost); + mTabHost.setup(); + } + } + + public void addTab(CompatTab tab) { + ... + TabSpec spec = mTabHost + .newTabSpec(tag) + .setIndicator(tab.getText()); // And optional icon + ... + mTabHost.addTab(spec); + } + + // The other important method, newTab() is part of + // the base implementation. +} +</pre> + +<p>You now have two implementations of <code>CompatTab</code> and <code>TabHelper</code>: one that works on devices running Android 3.0 or later and uses new APIs, and another that works on devices running Android 2.0 or later and uses older APIs. The next lesson discusses using these implementations in your application.</p> diff --git a/docs/html/training/backward-compatible-ui/using-component.jd b/docs/html/training/backward-compatible-ui/using-component.jd new file mode 100644 index 0000000..4bf7fa0 --- /dev/null +++ b/docs/html/training/backward-compatible-ui/using-component.jd @@ -0,0 +1,143 @@ +page.title=Using the Version-Aware Component +parent.title=Creating Backward-Compatible UIs +parent.link=index.html + +trainingnavtop=true +previous.title=Creating an Implementation with Older APIs +previous.link=older-implementation.html + +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> + +<h2>This lesson teaches you to:</h2> +<ol> + <li><a href="#switching-logic">Add the Switching Logic</a></li> + <li><a href="#layout">Create a Version-Aware Activity Layout</a></li> + <li><a href="#use-tabhelper">Use TabHelper in Your Activity</a></li> +</ol> + +<h2>Try it out</h2> + +<div class="download-box"> +<a href="http://developer.android.com/shareables/training/TabCompat.zip" + class="button">Download the sample app</a> +<p class="filename">TabCompat.zip</p> +</div> + +</div> +</div> + +<p>Now that you have two implementations of <code>TabHelper</code> and <code>CompatTab</code>—one for Android 3.0 and later and one for earlier versions of the platform—it's time to do something with these implementations. This lesson discusses creating the logic for switching between these implementations, creating version-aware layouts, and finally using the backward-compatible UI component.</p> + +<h2 id="switching-logic">Add the Switching Logic</h2> + +<p>The <code>TabHelper</code> abstract class acts as a <a href="http://en.wikipedia.org/wiki/Factory_(software_concept)">factory</a> for creating version-appropriate <code>TabHelper</code> and <code>CompatTab</code> instances, based on the current device's platform version:</p> + +<pre> +public abstract class TabHelper { + ... + // Usage is TabHelper.createInstance(activity) + public static TabHelper createInstance(FragmentActivity activity) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + return new TabHelperHoneycomb(activity); + } else { + return new TabHelperEclair(activity); + } + } + + // Usage is mTabHelper.newTab("tag") + public CompatTab newTab(String tag) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + return new CompatTabHoneycomb(mActivity, tag); + } else { + return new CompatTabEclair(mActivity, tag); + } + } + ... +} +</pre> + +<h2 id="layout">Create a Version-Aware Activity Layout</h2> + +<p>The next step is to provide layouts for your activity that can support the two tab implementations. For the older implementation (<code>TabHelperEclair</code>), you need to ensure that your activity layout contains a {@link android.widget.TabWidget} and {@link android.widget.TabHost}, along with a container for tab contents:</p> + +<p><strong>res/layout/main.xml:</strong></p> + +<pre> +<!-- This layout is for API level 5-10 only. --> +<TabHost xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@android:id/tabhost" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <LinearLayout + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:padding="5dp"> + + <TabWidget + android:id="@android:id/tabs" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + + <FrameLayout + android:id="@android:id/tabcontent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" /> + + </LinearLayout> +</TabHost> +</pre> + +<p>For the <code>TabHelperHoneycomb</code> implementation, all you need is a {@link android.widget.FrameLayout} to contain the tab contents, since the tab indicators are provided by the {@link android.app.ActionBar}:</p> + +<p><strong>res/layout-v11/main.xml:</strong></p> + +<pre> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@android:id/tabcontent" + android:layout_width="match_parent" + android:layout_height="match_parent" /> +</pre> + +<p>At runtime, Android will decide which version of the <code>main.xml</code> layout to inflate depending on the platform version. This is the same logic shown in the previous section to determine which <code>TabHelper</code> implementation to use.</p> + +<h2 id="use-tabhelper">Use TabHelper in Your Activity</h2> + +<p>In your activity's {@link android.app.Activity#onCreate onCreate()} method, you can obtain a <code>TabHelper</code> object and add tabs with the following code:</p> + +<pre> +{@literal @}Override +public void onCreate(Bundle savedInstanceState) { + setContentView(R.layout.main); + + TabHelper tabHelper = TabHelper.createInstance(this); + tabHelper.setUp(); + + CompatTab photosTab = tabHelper + .newTab("photos") + .setText(R.string.tab_photos); + tabHelper.addTab(photosTab); + + CompatTab videosTab = tabHelper + .newTab("videos") + .setText(R.string.tab_videos); + tabHelper.addTab(videosTab); +} +</pre> + +<p>When running the application, this code inflates the correct activity layout and instantiates either a <code>TabHelperHoneycomb</code> or <code>TabHelperEclair</code> object. The concrete class that's actually used is opaque to the activity, since they share the common <code>TabHelper</code> interface.</p> + +<p>Below are two screenshots of this implementation running on an Android 2.3 and Android 4.0 device.</p> + +<img src="{@docRoot}images/training/backward-compatible-ui-gb.png" + alt="Example screenshot of tabs running on an Android 2.3 device (using TabHelperEclair)." width="200"> + +<img src="{@docRoot}images/training/backward-compatible-ui-ics.png" + alt="Example screenshots of tabs running on an Android 4.0 device (using TabHelperHoneycomb)." width="200"> + +<p class="img-caption"><strong>Figure 1.</strong> Example screenshots of backward-compatible tabs running on an Android 2.3 device (using <code>TabHelperEclair</code>) and an Android 4.0 device (using <code>TabHelperHoneycomb</code>).</p> |