page.title=Creating Swipe Views with Tabs page.tags="viewpager","horizontal","paging","swipe view","tabs" trainingnavtop=true @jd:body <div id="tb-wrapper"> <div id="tb"> <h2>This lesson teaches you to</h2> <ol> <li><a href="#horizontal-paging">Implement Swipe Views</a></li> <li><a href="#tabs">Add Tabs to the Action Bar</a></li> <li><a href="#swipe-tabs">Change Tabs with Swipe Views</a></li> <li><a href="#PagerTitleStrip">Use a Title Strip Instead of Tabs</a></li> </ol> <h2>You should also read</h2> <ul> <li><a href="{@docRoot}training/design-navigation/descendant-lateral.html">Providing Descendant and Lateral Navigation</a></li> <li><a href="{@docRoot}design/building-blocks/tabs.html">Android Design: Tabs</a></li> <li><a href="{@docRoot}design/patterns/swipe-views.html">Android Design: Swipe Views</a></li> </ul> <h2>Try it out</h2> <div class="download-box"> <a href="http://developer.android.com/shareables/training/EffectiveNavigation.zip" class="button">Download the sample app</a> <p class="filename">EffectiveNavigation.zip</p> </div> </div> </div> <p>Swipe views provide lateral navigation between sibling screens such as tabs with a horizontal finger gesture (a pattern sometimes known as horizontal paging). This lesson teaches you how to create a tab layout with swipe views for switching between tabs, or how to show a title strip instead of tabs.</p> <div class="note design"> <p><strong>Swipe View Design</strong></p> <p>Before implementing these features, you should understand the concepts and recommendations as described in <a href="{@docRoot}training/design-navigation/descendant-lateral.html">Designing Effective Navigation</a> and the <a href="{@docRoot}design/patterns/swipe-views.html">Swipe Views</a> design guide.</p> </div> <h2 id="horizontal-paging">Implement Swipe Views</h2> <p>You can create swipe views in your app using the {@link android.support.v4.view.ViewPager} widget, available in the <a href="{@docRoot}tools/support-library/index.html">Support Library</a>. The {@link android.support.v4.view.ViewPager} is a layout widget in which each child view is a separate page (a separate tab) in the layout.</p> <p>To set up your layout with {@link android.support.v4.view.ViewPager}, add a {@code <ViewPager>} element to your XML layout. For example, if each page in the swipe view should consume the entire layout, then your layout looks like this:</p> <pre> <?xml version="1.0" encoding="utf-8"?> <android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent" /> </pre> <p>To insert child views that represent each page, you need to hook this layout to a {@link android.support.v4.view.PagerAdapter}. There are two kinds of adapter you can use:</p> <dl> <dt>{@link android.support.v4.app.FragmentPagerAdapter}</dt> <dd>This is best when navigating between sibling screens representing a fixed, small number of pages.</dd> <dt>{@link android.support.v4.app.FragmentStatePagerAdapter}</dt> <dd>This is best for paging across a collection of objects for which the number of pages is undetermined. It destroys fragments as the user navigates to other pages, minimizing memory usage.</dd> </dl> <p>For example, here's how you might use {@link android.support.v4.app.FragmentStatePagerAdapter} to swipe across a collection of {@link android.app.Fragment} objects:</p> <pre> public class CollectionDemoActivity extends FragmentActivity { // When requested, this adapter returns a DemoObjectFragment, // representing an object in the collection. DemoCollectionPagerAdapter mDemoCollectionPagerAdapter; ViewPager mViewPager; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_collection_demo); // ViewPager and its adapters use support library // fragments, so use getSupportFragmentManager. mDemoCollectionPagerAdapter = new DemoCollectionPagerAdapter( getSupportFragmentManager()); mViewPager = (ViewPager) findViewById(R.id.pager); mViewPager.setAdapter(mDemoCollectionPagerAdapter); } } // Since this is an object collection, use a FragmentStatePagerAdapter, // and NOT a FragmentPagerAdapter. public class DemoCollectionPagerAdapter extends FragmentStatePagerAdapter { public DemoCollectionPagerAdapter(FragmentManager fm) { super(fm); } {@literal @}Override public Fragment getItem(int i) { Fragment fragment = new DemoObjectFragment(); Bundle args = new Bundle(); // Our object is just an integer :-P args.putInt(DemoObjectFragment.ARG_OBJECT, i + 1); fragment.setArguments(args); return fragment; } {@literal @}Override public int getCount() { return 100; } {@literal @}Override public CharSequence getPageTitle(int position) { return "OBJECT " + (position + 1); } } // Instances of this class are fragments representing a single // object in our collection. public static class DemoObjectFragment extends Fragment { public static final String ARG_OBJECT = "object"; {@literal @}Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // The last two arguments ensure LayoutParams are inflated // properly. View rootView = inflater.inflate( R.layout.fragment_collection_object, container, false); Bundle args = getArguments(); ((TextView) rootView.findViewById(android.R.id.text1)).setText( Integer.toString(args.getInt(ARG_OBJECT))); return rootView; } } </pre> <p>This example shows only the code necessary to create the swipe views. The following sections show how you can add tabs to help facilitate navigation between pages.</p> <h2 id="tabs">Add Tabs to the Action Bar</h2> <p>Action bar <a href="{@docRoot}design/building-blocks/tabs.html">tabs</a> offer users a familiar interface for navigating between and identifying sibling screens in your app.</p> <p>To create tabs using {@link android.app.ActionBar}, you need to enable {@link android.app.ActionBar#NAVIGATION_MODE_TABS}, then create several instances of {@link android.app.ActionBar.Tab} and supply an implementation of the {@link android.app.ActionBar.TabListener} interface for each one. For example, in your activity's {@link android.app.Activity#onCreate onCreate()} method, you can use code similar to this:</p> <pre> {@literal @}Override public void onCreate(Bundle savedInstanceState) { final ActionBar actionBar = getActionBar(); ... // Specify that tabs should be displayed in the action bar. actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); // Create a tab listener that is called when the user changes tabs. ActionBar.TabListener tabListener = new ActionBar.TabListener() { public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) { // show the given tab } public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) { // hide the given tab } public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) { // probably ignore this event } }; // Add 3 tabs, specifying the tab's text and TabListener for (int i = 0; i < 3; i++) { actionBar.addTab( actionBar.newTab() .setText("Tab " + (i + 1)) .setTabListener(tabListener)); } } </pre> <p>How you handle the {@link android.app.ActionBar.TabListener} callbacks to change tabs depends on how you've constructed your content. But if you're using fragments for each tab with {@link android.support.v4.view.ViewPager} as shown above, the following section shows how to switch between pages when the user selects a tab and also update the selected tab when the user swipes between pages.</p> <h2 id="swipe-tabs">Change Tabs with Swipe Views</h2> <p>To switch between pages in a {@link android.support.v4.view.ViewPager} when the user selects a tab, implement your {@link android.app.ActionBar.TabListener} to select the appropriate page by calling {@link android.support.v4.view.ViewPager#setCurrentItem setCurrentItem()} on your {@link android.support.v4.view.ViewPager}:</p> <pre> {@literal @}Override public void onCreate(Bundle savedInstanceState) { ... // Create a tab listener that is called when the user changes tabs. ActionBar.TabListener tabListener = new ActionBar.TabListener() { public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) { // When the tab is selected, switch to the // corresponding page in the ViewPager. mViewPager.setCurrentItem(tab.getPosition()); } ... }; } </pre> <p>Likewise, you should select the corresponding tab when the user swipes between pages with a touch gesture. You can set up this behavior by implementing the {@link android.support.v4.view.ViewPager.OnPageChangeListener} interface to change the current tab each time the page changes. For example:</p> <pre> {@literal @}Override public void onCreate(Bundle savedInstanceState) { ... mViewPager = (ViewPager) findViewById(R.id.pager); mViewPager.setOnPageChangeListener( new ViewPager.SimpleOnPageChangeListener() { {@literal @}Override public void onPageSelected(int position) { // When swiping between pages, select the // corresponding tab. getActionBar().setSelectedNavigationItem(position); } }); ... } </pre> <h2 id="PagerTitleStrip">Use a Title Strip Instead of Tabs</h2> <p>If you don't want to include action bar tabs and prefer to provide <a href="{@docRoot}design/building-blocks/tabs.html#scrollable">scrollable tabs</a> for a shorter visual profile, you can use {@link android.support.v4.view.PagerTitleStrip} with your swipe views.</p> <p>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> <pre> <android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v4.view.PagerTitleStrip android:id="@+id/pager_title_strip" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:background="#33b5e5" android:textColor="#fff" android:paddingTop="4dp" android:paddingBottom="4dp" /> </android.support.v4.view.ViewPager> </pre>