Home | History | Annotate | Download | only in implementing-navigation
      1 page.title=Creating Swipe Views with Tabs
      2 page.tags="viewpager","horizontal","paging","swipe view","tabs"
      3 
      4 trainingnavtop=true
      5 
      6 @jd:body
      7 
      8 <div id="tb-wrapper">
      9 <div id="tb">
     10 
     11 <h2>This lesson teaches you to</h2>
     12 <ol>
     13   <li><a href="#horizontal-paging">Implement Swipe Views</a></li>
     14   <li><a href="#tabs">Add Tabs to the Action Bar</a></li>
     15   <li><a href="#swipe-tabs">Change Tabs with Swipe Views</a></li>
     16   <li><a href="#PagerTitleStrip">Use a Title Strip Instead of Tabs</a></li>
     17 </ol>
     18 
     19 
     20 <h2>You should also read</h2>
     21 <ul>
     22   <li><a href="{@docRoot}training/design-navigation/descendant-lateral.html">Providing Descendant and Lateral Navigation</a></li>
     23   <li><a href="{@docRoot}design/building-blocks/tabs.html">Android Design: Tabs</a></li>
     24   <li><a href="{@docRoot}design/patterns/swipe-views.html">Android Design: Swipe Views</a></li>
     25 </ul>
     26 
     27 <h2>Try it out</h2>
     28 
     29 <div class="download-box">
     30 <a href="http://developer.android.com/shareables/training/EffectiveNavigation.zip"
     31   class="button">Download the sample app</a>
     32 <p class="filename">EffectiveNavigation.zip</p>
     33 </div>
     34 
     35 </div>
     36 </div>
     37 
     38 
     39 <p>Swipe views provide lateral navigation between sibling screens such as tabs with
     40 a horizontal finger gesture (a pattern sometimes known as horizontal paging). This lesson teaches
     41 you how to create a tab layout with swipe views for switching between tabs, or how to show
     42 a title strip instead of tabs.</p>
     43 
     44 <div class="note design">
     45 <p><strong>Swipe View Design</strong></p>
     46 <p>Before implementing these features, you should understand the concepts and recommendations
     47 as described in <a href="{@docRoot}training/design-navigation/descendant-lateral.html">Designing
     48 Effective Navigation</a> and the <a href="{@docRoot}design/patterns/swipe-views.html">Swipe
     49 Views</a> design guide.</p>
     50 </div>
     51 
     52 
     53 
     54 
     55 
     56 <h2 id="horizontal-paging">Implement Swipe Views</h2>
     57 
     58 <p>You can create swipe views in your app using the {@link android.support.v4.view.ViewPager}
     59 widget, available in the
     60 <a href="{@docRoot}tools/support-library/index.html">Support Library</a>. The
     61 {@link android.support.v4.view.ViewPager} is a layout widget in which each child view is
     62 a separate page (a separate tab) in the layout.</p>
     63 
     64 <p>To set up your layout with {@link android.support.v4.view.ViewPager}, add a
     65 {@code &lt;ViewPager>} element to your XML layout. For example, if each page in the swipe view
     66 should consume the entire layout, then your layout looks like this:</p>
     67 
     68 <pre>
     69 &lt;?xml version="1.0" encoding="utf-8"?>
     70 &lt;android.support.v4.view.ViewPager
     71     xmlns:android="http://schemas.android.com/apk/res/android"
     72     android:id="@+id/pager"
     73     android:layout_width="match_parent"
     74     android:layout_height="match_parent" />
     75 </pre>
     76 
     77 <p>To insert child views that represent each page,
     78 you need to hook this layout to a {@link android.support.v4.view.PagerAdapter}.
     79 There are two kinds of adapter you can use:</p>
     80 
     81 <dl>
     82     <dt>{@link android.support.v4.app.FragmentPagerAdapter}</dt>
     83         <dd>This is best when navigating between sibling screens representing a fixed, small
     84         number of pages.</dd>
     85     <dt>{@link android.support.v4.app.FragmentStatePagerAdapter}</dt>
     86         <dd>This is best for paging across a collection of objects
     87 for which the number of pages is undetermined. It destroys
     88 fragments as the user navigates to other pages, minimizing memory usage.</dd>
     89 </dl>
     90 
     91 <p>For example, here's how you might use {@link android.support.v4.app.FragmentStatePagerAdapter}
     92 to swipe across a collection of {@link android.app.Fragment} objects:</p>
     93 
     94 <pre>
     95 public class CollectionDemoActivity extends FragmentActivity {
     96     // When requested, this adapter returns a DemoObjectFragment,
     97     // representing an object in the collection.
     98     DemoCollectionPagerAdapter mDemoCollectionPagerAdapter;
     99     ViewPager mViewPager;
    100 
    101     public void onCreate(Bundle savedInstanceState) {
    102         super.onCreate(savedInstanceState);
    103         setContentView(R.layout.activity_collection_demo);
    104 
    105         // ViewPager and its adapters use support library
    106         // fragments, so use getSupportFragmentManager.
    107         mDemoCollectionPagerAdapter =
    108                 new DemoCollectionPagerAdapter(
    109                         getSupportFragmentManager());
    110         mViewPager = (ViewPager) findViewById(R.id.pager);
    111         mViewPager.setAdapter(mDemoCollectionPagerAdapter);
    112     }
    113 }
    114 
    115 // Since this is an object collection, use a FragmentStatePagerAdapter,
    116 // and NOT a FragmentPagerAdapter.
    117 public class DemoCollectionPagerAdapter extends FragmentStatePagerAdapter {
    118     public DemoCollectionPagerAdapter(FragmentManager fm) {
    119         super(fm);
    120     }
    121 
    122     {@literal @}Override
    123     public Fragment getItem(int i) {
    124         Fragment fragment = new DemoObjectFragment();
    125         Bundle args = new Bundle();
    126         // Our object is just an integer :-P
    127         args.putInt(DemoObjectFragment.ARG_OBJECT, i + 1);
    128         fragment.setArguments(args);
    129         return fragment;
    130     }
    131 
    132     {@literal @}Override
    133     public int getCount() {
    134         return 100;
    135     }
    136 
    137     {@literal @}Override
    138     public CharSequence getPageTitle(int position) {
    139         return "OBJECT " + (position + 1);
    140     }
    141 }
    142 
    143 // Instances of this class are fragments representing a single
    144 // object in our collection.
    145 public static class DemoObjectFragment extends Fragment {
    146     public static final String ARG_OBJECT = "object";
    147 
    148     {@literal @}Override
    149     public View onCreateView(LayoutInflater inflater,
    150             ViewGroup container, Bundle savedInstanceState) {
    151         // The last two arguments ensure LayoutParams are inflated
    152         // properly.
    153         View rootView = inflater.inflate(
    154                 R.layout.fragment_collection_object, container, false);
    155         Bundle args = getArguments();
    156         ((TextView) rootView.findViewById(android.R.id.text1)).setText(
    157                 Integer.toString(args.getInt(ARG_OBJECT)));
    158         return rootView;
    159     }
    160 }
    161 </pre>
    162 
    163 <p>This example shows only the code necessary to create the swipe views. The following
    164 sections show how you can add tabs to help facilitate navigation between pages.</p>
    165 
    166 
    167 <h2 id="tabs">Add Tabs to the Action Bar</h2>
    168 
    169 <p>Action bar
    170 <a href="{@docRoot}design/building-blocks/tabs.html">tabs</a> offer users a familiar interface
    171 for navigating between and identifying sibling screens in your app.</p>
    172 
    173 <p>To create tabs using {@link android.app.ActionBar}, you need to enable
    174 {@link android.app.ActionBar#NAVIGATION_MODE_TABS}, then create several instances of
    175 {@link android.app.ActionBar.Tab} and supply an implementation of
    176 the {@link android.app.ActionBar.TabListener} interface for each one.
    177 For example, in your activity's {@link
    178 android.app.Activity#onCreate onCreate()} method, you can use code similar to this:</p>
    179 
    180 <pre>
    181 {@literal @}Override
    182 public void onCreate(Bundle savedInstanceState) {
    183     final ActionBar actionBar = getActionBar();
    184     ...
    185 
    186     // Specify that tabs should be displayed in the action bar.
    187     actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    188 
    189     // Create a tab listener that is called when the user changes tabs.
    190     ActionBar.TabListener tabListener = new ActionBar.TabListener() {
    191         public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
    192             // show the given tab
    193         }
    194 
    195         public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
    196             // hide the given tab
    197         }
    198 
    199         public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
    200             // probably ignore this event
    201         }
    202     };
    203 
    204     // Add 3 tabs, specifying the tab's text and TabListener
    205     for (int i = 0; i &lt; 3; i++) {
    206         actionBar.addTab(
    207                 actionBar.newTab()
    208                         .setText("Tab " + (i + 1))
    209                         .setTabListener(tabListener));
    210     }
    211 }
    212 </pre>
    213 
    214 <p>How you handle the {@link android.app.ActionBar.TabListener} callbacks to change tabs
    215 depends on how you've constructed your content. But if you're using fragments for each tab with
    216 {@link android.support.v4.view.ViewPager} as shown above, the following
    217 section shows how to switch between pages when the user selects a tab and also update the selected
    218 tab when the user swipes between pages.</p>
    219 
    220 
    221 <h2 id="swipe-tabs">Change Tabs with Swipe Views</h2>
    222 
    223 <p>To switch between pages in a {@link android.support.v4.view.ViewPager} when the user selects
    224 a tab, implement your {@link android.app.ActionBar.TabListener} to select the appropriate page
    225 by calling {@link android.support.v4.view.ViewPager#setCurrentItem setCurrentItem()} on your
    226 {@link android.support.v4.view.ViewPager}:</p>
    227 
    228 <pre>
    229 {@literal @}Override
    230 public void onCreate(Bundle savedInstanceState) {
    231     ...
    232 
    233     // Create a tab listener that is called when the user changes tabs.
    234     ActionBar.TabListener tabListener = new ActionBar.TabListener() {
    235         public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
    236             // When the tab is selected, switch to the
    237             // corresponding page in the ViewPager.
    238             mViewPager.setCurrentItem(tab.getPosition());
    239         }
    240         ...
    241     };
    242 }
    243 </pre>
    244 
    245 <p>Likewise, you should select the corresponding tab when the user swipes between pages with a
    246 touch gesture. You can set up this behavior by implementing the
    247 {@link android.support.v4.view.ViewPager.OnPageChangeListener} interface to change
    248 the current tab each time the page changes. For example:</p>
    249 
    250 <pre>
    251 {@literal @}Override
    252 public void onCreate(Bundle savedInstanceState) {
    253     ...
    254 
    255     mViewPager = (ViewPager) findViewById(R.id.pager);
    256     mViewPager.setOnPageChangeListener(
    257             new ViewPager.SimpleOnPageChangeListener() {
    258                 {@literal @}Override
    259                 public void onPageSelected(int position) {
    260                     // When swiping between pages, select the
    261                     // corresponding tab.
    262                     getActionBar().setSelectedNavigationItem(position);
    263                 }
    264             });
    265     ...
    266 }
    267 </pre>
    268 
    269 
    270 
    271 <h2 id="PagerTitleStrip">Use a Title Strip Instead of Tabs</h2>
    272 
    273 <p>If you don't want to include action bar tabs and prefer to provide
    274 <a href="{@docRoot}design/building-blocks/tabs.html#scrollable">scrollable tabs</a> for a shorter
    275 visual profile, you can use {@link android.support.v4.view.PagerTitleStrip} with
    276 your swipe views.</p>
    277 
    278 <p>Below is an example layout XML file for an
    279 activity whose entire contents are a {@link android.support.v4.view.ViewPager} and a top-aligned
    280 {@link android.support.v4.view.PagerTitleStrip} inside it. Individual pages (provided by the
    281 adapter) occupy the remaining space inside the {@link android.support.v4.view.ViewPager}.</p>
    282 
    283 <pre>
    284 &lt;android.support.v4.view.ViewPager
    285     xmlns:android="http://schemas.android.com/apk/res/android"
    286     android:id="@+id/pager"
    287     android:layout_width="match_parent"
    288     android:layout_height="match_parent"&gt;
    289 
    290     &lt;android.support.v4.view.PagerTitleStrip
    291         android:id="@+id/pager_title_strip"
    292         android:layout_width="match_parent"
    293         android:layout_height="wrap_content"
    294         android:layout_gravity="top"
    295         android:background="#33b5e5"
    296         android:textColor="#fff"
    297         android:paddingTop="4dp"
    298         android:paddingBottom="4dp" /&gt;
    299 
    300 &lt;/android.support.v4.view.ViewPager&gt;
    301 </pre>
    302