OSDN Git Service

docs: Android Training: Creating Backward-Compatible UIs class
[android-x86/frameworks-base.git] / docs / html / training / backward-compatible-ui / older-implementation.jd
1 page.title=Creating an Implementation with Older APIs
2 parent.title=Creating Backward-Compatible UIs
3 parent.link=index.html
4
5 trainingnavtop=true
6 previous.title=Proxying to the New APIs
7 previous.link=new-implementation.html
8 next.title=Using the Version-Aware Component
9 next.link=using-component.html
10
11 @jd:body
12
13 <div id="tb-wrapper">
14 <div id="tb">
15
16 <h2>This lesson teaches you to:</h2>
17 <ol>
18   <li><a href="#decide-substitute">Decide on a Substitute Solution</a></li>
19   <li><a href="#older-tabs">Implement Tabs Using Older APIs</a></li>
20 </ol>
21
22 <h2>Try it out</h2>
23
24 <div class="download-box">
25 <a href="http://developer.android.com/shareables/training/TabCompat.zip"
26   class="button">Download the sample app</a>
27 <p class="filename">TabCompat.zip</p>
28 </div>
29
30 </div>
31 </div>
32
33
34 <p>This lesson discusses how to create an implementation that mirrors newer APIs yet supports older devices.</p>
35
36 <h2 id="decide-substitute">Decide on a Substitute Solution</h2>
37
38 <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>
39
40 <ul>
41
42 <li>
43 <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>
44 </li>
45
46 <li>
47 <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>
48 </li>
49
50 <li>
51 <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>
52 </li>
53
54 <li>
55 <p>{@link android.widget.ListPopupWindow} and {@link android.widget.PopupMenu} widgets can be implemented using {@link android.widget.PopupWindow} widgets.</p>
56 </li>
57
58 </ul>
59
60 <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&mdash;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>
61
62 <h2 id="older-tabs">Implement Tabs Using Older APIs</h2>
63
64 <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>
65
66
67 <img src="{@docRoot}images/training/backward-compatible-ui-classes-eclair.png"
68   alt="Class diagram for the Eclair implementation of tabs." id="figure-classes">
69
70 <p class="img-caption"><strong>Figure 1.</strong> Class diagram for the Eclair implementation of tabs.</p>
71
72 <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>
73
74 <pre>
75 public class CompatTabEclair extends CompatTab {
76     // Store these properties in the instance,
77     // as there is no ActionBar.Tab object.
78     private CharSequence mText;
79     ...
80
81     public CompatTab setText(int resId) {
82         // Our older implementation simply stores this
83         // information in the object instance.
84         mText = mActivity.getResources().getText(resId);
85         return this;
86     }
87
88     ...
89     // Do the same for other properties (icon, callback, etc.)
90 }
91 </pre>
92
93 <p>The <code>TabHelperEclair</code> implementation makes use of methods on the
94 {@link android.widget.TabHost} widget for creating {@link android.widget.TabHost.TabSpec}
95 objects and tab indicators:</p>
96
97 <pre>
98 public class TabHelperEclair extends TabHelper {
99     private TabHost mTabHost;
100     ...
101
102     protected void setUp() {
103         if (mTabHost == null) {
104             // Our activity layout for pre-Honeycomb devices
105             // must contain a TabHost.
106             mTabHost = (TabHost) mActivity.findViewById(
107                     android.R.id.tabhost);
108             mTabHost.setup();
109         }
110     }
111
112     public void addTab(CompatTab tab) {
113         ...
114         TabSpec spec = mTabHost
115                 .newTabSpec(tag)
116                 .setIndicator(tab.getText()); // And optional icon
117         ...
118         mTabHost.addTab(spec);
119     }
120
121     // The other important method, newTab() is part of
122     // the base implementation.
123 }
124 </pre>
125
126 <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>