1page.title=Creating Swipe Views with Tabs 2page.tags="viewpager","horizontal","paging","swipe view","tabs" 3 4trainingnavtop=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 40a horizontal finger gesture (a pattern sometimes known as horizontal paging). This lesson teaches 41you how to create a tab layout with swipe views for switching between tabs, or how to show 42a 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 47as described in <a href="{@docRoot}training/design-navigation/descendant-lateral.html">Designing 48Effective Navigation</a> and the <a href="{@docRoot}design/patterns/swipe-views.html">Swipe 49Views</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} 59widget, 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 62a 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 <ViewPager>} element to your XML layout. For example, if each page in the swipe view 66should consume the entire layout, then your layout looks like this:</p> 67 68<pre> 69<?xml version="1.0" encoding="utf-8"?> 70<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, 78you need to hook this layout to a {@link android.support.v4.view.PagerAdapter}. 79There 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 87for which the number of pages is undetermined. It destroys 88fragments 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} 92to swipe across a collection of {@link android.app.Fragment} objects:</p> 93 94<pre> 95public 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. 117public 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. 145public 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 164sections 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 171for 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 176the {@link android.app.ActionBar.TabListener} interface for each one. 177For example, in your activity's {@link 178android.app.Activity#onCreate onCreate()} method, you can use code similar to this:</p> 179 180<pre> 181{@literal @}Override 182public 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 < 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 215depends 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 217section shows how to switch between pages when the user selects a tab and also update the selected 218tab 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 224a tab, implement your {@link android.app.ActionBar.TabListener} to select the appropriate page 225by 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 230public 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 246touch gesture. You can set up this behavior by implementing the 247{@link android.support.v4.view.ViewPager.OnPageChangeListener} interface to change 248the current tab each time the page changes. For example:</p> 249 250<pre> 251{@literal @}Override 252public 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 275visual profile, you can use {@link android.support.v4.view.PagerTitleStrip} with 276your swipe views.</p> 277 278<p>Below is an example layout XML file for an 279activity 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 281adapter) occupy the remaining space inside the {@link android.support.v4.view.ViewPager}.</p> 282 283<pre> 284<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"> 289 290 <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" /> 299 300</android.support.v4.view.ViewPager> 301</pre> 302