Home | History | Annotate | Download | only in implementing-navigation
      1 page.title=Implementing Lateral Navigation
      2 parent.title=Implementing Effective Navigation
      3 parent.link=index.html
      4 
      5 trainingnavtop=true
      6 next.title=Implementing Ancestral Navigation
      7 next.link=ancestral.html
      8 
      9 @jd:body
     10 
     11 <div id="tb-wrapper">
     12 <div id="tb">
     13 
     14 <h2>This lesson teaches you to</h2>
     15 <ol>
     16   <li><a href="#tabs">Implement Tabs</a></li>
     17   <li><a href="#horizontal-paging">Implement Horizontal Paging (Swipe Views)</a></li>
     18   <li><a href="#swipe-tabs">Implement Swiping Between Tabs</a></li>
     19 </ol>
     20 
     21 <h2>You should also read</h2>
     22 <ul>
     23   <li><a href="{@docRoot}training/design-navigation/descendant-lateral.html">Providing Descendant and Lateral Navigation</a></li>
     24   <li><a href="{@docRoot}design/building-blocks/tabs.html">Android Design: Tabs</a></li>
     25   <li><a href="{@docRoot}design/patterns/swipe-views.html">Android Design: Swipe Views</a></li>
     26 </ul>
     27 
     28 <h2>Try it out</h2>
     29 
     30 <div class="download-box">
     31 <a href="http://developer.android.com/shareables/training/EffectiveNavigation.zip"
     32   class="button">Download the sample app</a>
     33 <p class="filename">EffectiveNavigation.zip</p>
     34 </div>
     35 
     36 </div>
     37 </div>
     38 
     39 
     40 <p><em>Lateral navigation</em> is navigation between sibling screens in the application's screen hierarchy (sometimes referred to as a screen map). The most prominent lateral navigation patterns are tabs and horizontal paging (also known as swipe views). This pattern and others are described in <a href="{@docRoot}training/design-navigation/descendant-lateral.html">Designing Effective Navigation</a>. This lesson covers how to implement several of the primary lateral navigation patterns in Android.</p>
     41 
     42 <h2 id="tabs">Implement Tabs</h2>
     43 
     44 <p>Tabs allow the user to navigate between sibling screens by selecting the appropriate tab indicator available at the top of the display. In Android 3.0 and later, tabs are implemented using the {@link android.app.ActionBar} class, and are generally set up in {@link android.app.Activity#onCreate Activity.onCreate()}. In some cases, such as when horizontal space is limited and/or the number of tabs is large, an appropriate alternate presentation for tabs is a dropdown list (sometimes implemented using a {@link android.widget.Spinner}).</p>
     45 
     46 <p>In previous versions of Android, tabs could be implemented using a {@link android.widget.TabWidget} and {@link android.widget.TabHost}. For details, see the <a href="{@docRoot}resources/tutorials/views/hello-tabwidget.html">Hello, Views</a> tutorial.</p>
     47 
     48 <p>As of Android 3.0, however, you should use either {@link android.app.ActionBar#NAVIGATION_MODE_TABS} or {@link android.app.ActionBar#NAVIGATION_MODE_LIST} along with the {@link android.app.ActionBar} class.</p>
     49 
     50 <h3>Implement the Tabs Pattern with NAVIGATION_MODE_TABS</h3>
     51 
     52 <p>To create tabs, you can use the following code in your activity's {@link android.app.Activity#onCreate onCreate()} method. Note that the exact presentation of tabs may vary per device and by the current device configuration, to make best use of available screen space. For example, Android may automatically collapse tabs into a dropdown list if tabs don't fit horizontally in the action bar.</p>
     53 
     54 <pre>
     55 {@literal @}Override
     56 public void onCreate(Bundle savedInstanceState) {
     57     ...
     58     final ActionBar actionBar = getActionBar();
     59 
     60     // Specify that tabs should be displayed in the action bar.
     61     actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
     62 
     63     // Create a tab listener that is called when the user changes tabs.
     64     ActionBar.TabListener tabListener = new ActionBar.TabListener() {
     65         public void onTabSelected(ActionBar.Tab tab,
     66                 FragmentTransaction ft) { }
     67 
     68         public void onTabUnselected(ActionBar.Tab tab,
     69                 FragmentTransaction ft) { }
     70 
     71         public void onTabReselected(ActionBar.Tab tab,
     72                 FragmentTransaction ft) { }
     73     };
     74 
     75     // Add 3 tabs.
     76     for (int i = 0; i &lt; 3; i++) {
     77         actionBar.addTab(
     78                 actionBar.newTab()
     79                         .setText("Tab " + (i + 1))
     80                         .setTabListener(tabListener));
     81     }
     82     ...
     83 }
     84 </pre>
     85 
     86 <h3>Implement the Tabs Pattern with NAVIGATION_MODE_LIST</h3>
     87 
     88 <p>To use a dropdown list instead, use the following code in your activity's {@link android.app.Activity#onCreate onCreate()} method. Dropdown lists are often preferable in cases where more information must be shown per navigation item, such as unread message counts, or where the number of available navigation items is large.</p>
     89 
     90 <pre>
     91 {@literal @}Override
     92 public void onCreate(Bundle savedInstanceState) {
     93     ...
     94     final ActionBar actionBar = getActionBar();
     95 
     96     // Specify that a dropdown list should be displayed in the action bar.
     97     actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
     98 
     99     actionBar.setListNavigationCallbacks(
    100             // Specify a SpinnerAdapter to populate the dropdown list.
    101             new ArrayAdapter<String>(
    102                     actionBar.getThemedContext(),
    103                     android.R.layout.simple_list_item_1,
    104                     android.R.id.text1,
    105                     new String[]{ "Tab 1", "Tab 2", "Tab 3" }),
    106 
    107             // Provide a listener to be called when an item is selected.
    108             new ActionBar.OnNavigationListener() {
    109                 public boolean onNavigationItemSelected(
    110                         int position, long id) {
    111                     // Take action here, e.g. switching to the
    112                     // corresponding fragment.
    113                     return true;
    114                 }
    115             });
    116     ...
    117 }
    118 </pre>
    119 
    120 <h2 id="horizontal-paging">Implement Horizontal Paging (Swipe Views)</h2>
    121 
    122 <p>Horizontal paging, or swipe views, allow users to <a href="{@docRoot}design/patterns/swipe-views.html">swipe</a> horizontally on the current screen to navigate to adjacent screens. This pattern can be implemented using the {@link android.support.v4.view.ViewPager} widget, currently available as part of the <a href="{@docRoot}tools/extras/support-library.html">Android Support Package</a>. For navigating between sibling screens representing a fixed number of sections, it's best to provide the {@link android.support.v4.view.ViewPager} with a {@link android.support.v4.app.FragmentPagerAdapter}. For horizontal paging across collections of objects, it's best to use a {@link android.support.v4.app.FragmentStatePagerAdapter}, which destroys fragments as the user navigates to other pages, minimizing memory usage.</p>
    123 
    124 <p>Below is an example of using a {@link android.support.v4.view.ViewPager} to swipe across a collection of objects.</p>
    125 
    126 <pre>
    127 public class CollectionDemoActivity extends FragmentActivity {
    128     // When requested, this adapter returns a DemoObjectFragment,
    129     // representing an object in the collection.
    130     DemoCollectionPagerAdapter mDemoCollectionPagerAdapter;
    131     ViewPager mViewPager;
    132 
    133     public void onCreate(Bundle savedInstanceState) {
    134         // ViewPager and its adapters use support library
    135         // fragments, so use getSupportFragmentManager.
    136         mDemoCollectionPagerAdapter =
    137                 new DemoCollectionPagerAdapter(
    138                         getSupportFragmentManager());
    139         mViewPager = (ViewPager) findViewById(R.id.pager);
    140         mViewPager.setAdapter(mDemoCollectionPagerAdapter);
    141     }
    142 }
    143 
    144 // Since this is an object collection, use a FragmentStatePagerAdapter,
    145 // and NOT a FragmentPagerAdapter.
    146 public class DemoCollectionPagerAdapter extends
    147         FragmentStatePagerAdapter {
    148     public DemoCollectionPagerAdapter(FragmentManager fm) {
    149         super(fm);
    150     }
    151 
    152     {@literal @}Override
    153     public Fragment getItem(int i) {
    154         Fragment fragment = new DemoObjectFragment();
    155         Bundle args = new Bundle();
    156         // Our object is just an integer :-P
    157         args.putInt(DemoObjectFragment.ARG_OBJECT, i + 1);
    158         fragment.setArguments(args);
    159         return fragment;
    160     }
    161 
    162     {@literal @}Override
    163     public int getCount() {
    164         return 100;
    165     }
    166 
    167     {@literal @}Override
    168     public CharSequence getPageTitle(int position) {
    169         return "OBJECT " + (position + 1);
    170     }
    171 }
    172 
    173 // Instances of this class are fragments representing a single
    174 // object in our collection.
    175 public static class DemoObjectFragment extends Fragment {
    176     public static final String ARG_OBJECT = "object";
    177 
    178     {@literal @}Override
    179     public View onCreateView(LayoutInflater inflater,
    180             ViewGroup container, Bundle savedInstanceState) {
    181         // The last two arguments ensure LayoutParams are inflated
    182         // properly.
    183         View rootView = inflater.inflate(
    184                 R.layout.fragment_collection_object, container, false);
    185         Bundle args = getArguments();
    186         ((TextView) rootView.findViewById(android.R.id.text1)).setText(
    187                 Integer.toString(args.getInt(ARG_OBJECT)));
    188         return rootView;
    189     }
    190 }
    191 </pre>
    192 
    193 <p>You can also add indicators to your horizontal paging UI by adding a {@link android.support.v4.view.PagerTitleStrip}. Below is an example layout XML file for an activity whose entire contents are a {@link android.support.v4.view.ViewPager} and a top-aligned {@link android.support.v4.view.PagerTitleStrip} inside it. Individual pages (provided by the adapter) occupy the remaining space inside the {@link android.support.v4.view.ViewPager}.</p>
    194 
    195 <pre>
    196 &lt;android.support.v4.view.ViewPager
    197     xmlns:android="http://schemas.android.com/apk/res/android"
    198     android:id="@+id/pager"
    199     android:layout_width="match_parent"
    200     android:layout_height="match_parent"&gt;
    201 
    202     &lt;android.support.v4.view.PagerTitleStrip
    203         android:id="@+id/pager_title_strip"
    204         android:layout_width="match_parent"
    205         android:layout_height="wrap_content"
    206         android:layout_gravity="top"
    207         android:background="#33b5e5"
    208         android:textColor="#fff"
    209         android:paddingTop="4dp"
    210         android:paddingBottom="4dp" /&gt;
    211 
    212 &lt;/android.support.v4.view.ViewPager&gt;
    213 </pre>
    214 
    215 <h2 id="swipe-tabs">Implement Swiping Between Tabs</h2>
    216 
    217 <p>One of the key design recommendations in Android 4.0 for tabs is to <a href="{@docRoot}design/patterns/swipe-views.html">allow swiping</a> between them where appropriate. This behavior enables users to swipe horizontally across the selected tab's contents to navigate to adjacent tabs, without needed to directly interact with the tabs themselves. To implement this, you can use a {@link android.support.v4.view.ViewPager} in conjunction with the {@link android.app.ActionBar} tabs API.</p>
    218 
    219 <p>Upon observing the current page changing, select the corresponding tab. You can set up this behavior using an {@link android.support.v4.view.ViewPager.OnPageChangeListener} in your activity's {@link android.app.Activity#onCreate onCreate()} method:</p>
    220 
    221 <pre>
    222 {@literal @}Override
    223 public void onCreate(Bundle savedInstanceState) {
    224     ...
    225     mViewPager.setOnPageChangeListener(
    226             new ViewPager.SimpleOnPageChangeListener() {
    227                 {@literal @}Override
    228                 public void onPageSelected(int position) {
    229                     // When swiping between pages, select the
    230                     // corresponding tab.
    231                     getActionBar().setSelectedNavigationItem(position);
    232                 }
    233             });
    234     ...
    235 }
    236 </pre>
    237 
    238 <p>And upon selecting a tab, switch to the corresponding page in the {@link android.support.v4.view.ViewPager}. To do this, add an {@link android.app.ActionBar.TabListener} to your tab when creating it using the {@link android.app.ActionBar#newTab newTab()} method:</p>
    239 
    240 <pre>
    241 actionBar.newTab()
    242         ...
    243         .setTabListener(new ActionBar.TabListener() {
    244             public void onTabSelected(ActionBar.Tab tab,
    245                     FragmentTransaction ft) {
    246                 // When the tab is selected, switch to the
    247                 // corresponding page in the ViewPager.
    248                 mViewPager.setCurrentItem(tab.getPosition());
    249             }
    250             ...
    251         }));
    252 </pre>
    253