blob: bb9d78c288e2207212e597f382108c7d64f68494 [file] [log] [blame]
Scott Main7c840552013-03-26 18:53:01 -07001page.title=Creating Swipe Views with Tabs
Scott Mainfb56b4f2013-07-31 10:58:48 -07002page.tags="viewpager","horizontal","paging","swipe view","tabs"
Roman Nurik19266f72012-03-12 21:48:47 -07003
4trainingnavtop=true
Roman Nurik19266f72012-03-12 21:48:47 -07005
6@jd:body
7
8<div id="tb-wrapper">
9<div id="tb">
10
11<h2>This lesson teaches you to</h2>
12<ol>
Scott Main7c840552013-03-26 18:53:01 -070013 <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>
Roman Nurik19266f72012-03-12 21:48:47 -070017</ol>
18
Scott Main7c840552013-03-26 18:53:01 -070019
Roman Nurik19266f72012-03-12 21:48:47 -070020<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
Scott Main7c840552013-03-26 18:53:01 -070039<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>
Roman Nurik19266f72012-03-12 21:48:47 -070043
Scott Main7c840552013-03-26 18:53:01 -070044<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>
Roman Nurik19266f72012-03-12 21:48:47 -070051
Roman Nurik19266f72012-03-12 21:48:47 -070052
Roman Nurik19266f72012-03-12 21:48:47 -070053
Roman Nurik19266f72012-03-12 21:48:47 -070054
Roman Nurik19266f72012-03-12 21:48:47 -070055
Scott Main7c840552013-03-26 18:53:01 -070056<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
Scott Main4e2c9dc2013-07-23 19:35:17 -070060<a href="{@docRoot}tools/support-library/index.html">Support Library</a>. The
Scott Main7c840552013-03-26 18:53:01 -070061{@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 &lt;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>
Roman Nurik19266f72012-03-12 21:48:47 -070067
68<pre>
Scott Main7c840552013-03-26 18:53:01 -070069&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" />
Roman Nurik19266f72012-03-12 21:48:47 -070075</pre>
76
Scott Main7c840552013-03-26 18:53:01 -070077<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>
Roman Nurik19266f72012-03-12 21:48:47 -070080
Scott Main7c840552013-03-26 18:53:01 -070081<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>
Roman Nurik19266f72012-03-12 21:48:47 -070090
Scott Main7c840552013-03-26 18:53:01 -070091<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>
Roman Nurik19266f72012-03-12 21:48:47 -070093
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) {
Scott Maina15afd22013-03-12 09:25:22 -0700102 super.onCreate(savedInstanceState);
103 setContentView(R.layout.activity_collection_demo);
104
Roman Nurik19266f72012-03-12 21:48:47 -0700105 // 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.
Scott Main7c840552013-03-26 18:53:01 -0700117public class DemoCollectionPagerAdapter extends FragmentStatePagerAdapter {
Roman Nurik19266f72012-03-12 21:48:47 -0700118 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
Scott Main7c840552013-03-26 18:53:01 -0700163<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 &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
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>
Roman Nurik19266f72012-03-12 21:48:47 -0700282
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;
Scott Main0c391522013-05-15 14:38:16 -0700301</pre>