1page.title=Using ViewPager for Screen Slides
2trainingnavtop=true
3
4@jd:body
5
6  <div id="tb-wrapper">
7    <div id="tb">
8      <h2>This lesson teaches you to</h2>
9         <ol>
10            <li><a href="#views">Create the Views</a></li>
11            <li><a href="#fragment">Create the Fragment</a></li>
12            <li><a href="#viewpager">Add a ViewPager</a></li>
13            <li><a href="#pagetransformer">Customize the Animation with PageTransformer</a></li>
14        </ol>
15        <h2>
16          Try it out
17        </h2>
18        <div class="download-box">
19          <a href="{@docRoot}shareables/training/Animations.zip" class=
20          "button">Download the sample app</a>
21          <p class="filename">
22            Animations.zip
23          </p>
24        </div>
25    </div>
26  </div>
27  <p>
28      Screen slides are transitions between one entire screen to another and are common with UIs
29      like setup wizards or slideshows. This lesson shows you how to do screen slides with
30      a {@link android.support.v4.view.ViewPager} provided by the <a href=
31      "{@docRoot}tools/support-library/index.html">support library</a>.
32      {@link android.support.v4.view.ViewPager}s can animate screen slides
33      automatically. Here's what a screen slide looks like that transitions from
34      one screen of content to the next:
35    </p>
36
37    <div class="framed-galaxynexus-land-span-8">
38      <video class="play-on-hover" autoplay>
39        <source src="anim_screenslide.mp4" type="video/mp4">
40        <source src="anim_screenslide.webm" type="video/webm">
41        <source src="anim_screenslide.ogv" type="video/ogg">
42      </video>
43    </div>
44
45    <div class="figure-caption">
46      Screen slide animation
47      <div class="video-instructions">&nbsp;</div>
48    </div>
49
50<p>If you want to jump ahead and see a full working example,
51<a href="{@docRoot}shareables/training/Animations.zip">download</a>
52and run the sample app and select the Screen Slide example. See the
53following files for the code implementation:</p>
54<ul>
55  <li><code>src/ScreenSlidePageFragment.java</code></li>
56  <li><code>src/ScreenSlideActivity.java</code></li>
57  <li><code>layout/activity_screen_slide.xml</code></li>
58  <li><code>layout/fragment_screen_slide_page.xml</code></li>
59</ul>
60
61<h2 id="views">Create the Views</h2>
62  <p>Create a layout file that you'll later use for the content of a fragment. The following example
63    contains a text view to display some text:
64
65<pre>
66&lt;!-- fragment_screen_slide_page.xml --&gt;
67&lt;ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
68    android:id="&#64;+id/content"
69    android:layout_width="match_parent"
70    android:layout_height="match_parent" &gt;
71
72    &lt;TextView style="?android:textAppearanceMedium"
73        android:padding="16dp"
74        android:lineSpacingMultiplier="1.2"
75        android:layout_width="match_parent"
76        android:layout_height="wrap_content"
77        android:text="@string/lorem_ipsum" /&gt;
78&lt;/ScrollView&gt;
79</pre>
80
81  <p>Define also a string for the contents of the fragment.</p>
82
83<h2 id="fragment">Create the Fragment</h2>
84<p>Create a {@link android.support.v4.app.Fragment} class that returns the layout
85that you just created in the {@link android.app.Fragment#onCreateView onCreateView()}
86  method. You can then create instances of this fragment in the parent activity whenever you need a new page to
87  display to the user:</p>
88
89
90<pre>
91import android.support.v4.app.Fragment;
92...
93public class ScreenSlidePageFragment extends Fragment {
94
95    &#64;Override
96    public View onCreateView(LayoutInflater inflater, ViewGroup container,
97            Bundle savedInstanceState) {
98        ViewGroup rootView = (ViewGroup) inflater.inflate(
99                R.layout.fragment_screen_slide_page, container, false);
100
101        return rootView;
102    }
103}
104</pre>
105
106<h2 id="viewpager">Add a ViewPager</h2>
107
108<p>{@link android.support.v4.view.ViewPager}s have built-in swipe gestures to transition
109  through pages, and they display screen slide animations by default, so you don't need to create any. {@link android.support.v4.view.ViewPager}s use
110{@link android.support.v4.view.PagerAdapter}s as a supply for new pages to display, so the {@link android.support.v4.view.PagerAdapter} will use the
111fragment class that you created earlier.
112  </p>
113
114<p>To begin, create a layout that contains a {@link android.support.v4.view.ViewPager}:</p>
115
116<pre>
117&lt;!-- activity_screen_slide.xml --&gt;
118&lt;android.support.v4.view.ViewPager
119    xmlns:android="http://schemas.android.com/apk/res/android"
120    android:id="@+id/pager"
121    android:layout_width="match_parent"
122    android:layout_height="match_parent" /&gt;
123</pre>
124
125<p>Create an activity that does the following things:
126</p>
127
128<ul>
129  <li>Sets the content view to be the layout with the {@link android.support.v4.view.ViewPager}.</li>
130  <li>Creates a class that extends the {@link android.support.v13.app.FragmentStatePagerAdapter} abstract class and implements
131  the {@link android.support.v4.app.FragmentStatePagerAdapter#getItem getItem()} method to supply
132    instances of <code>ScreenSlidePageFragment</code> as new pages. The pager adapter also requires that you implement the
133    {@link android.support.v4.view.PagerAdapter#getCount getCount()} method, which returns the amount of pages the adapter will create (five in the example).
134  <li>Hooks up the {@link android.support.v4.view.PagerAdapter} to the {@link android.support.v4.view.ViewPager}</code>.</li>
135  <li>Handles the device's back button by moving backwards in the virtual stack of fragments.
136    If the user is already on the first page, go back on the activity back stack.</li>
137</ul>
138
139<pre>
140import android.support.v4.app.Fragment;
141import android.support.v4.app.FragmentManager;
142...
143public class ScreenSlidePagerActivity extends FragmentActivity {
144    /**
145     * The number of pages (wizard steps) to show in this demo.
146     */
147    private static final int NUM_PAGES = 5;
148
149    /**
150     * The pager widget, which handles animation and allows swiping horizontally to access previous
151     * and next wizard steps.
152     */
153    private ViewPager mPager;
154
155    /**
156     * The pager adapter, which provides the pages to the view pager widget.
157     */
158    private PagerAdapter mPagerAdapter;
159
160    &#64;Override
161    protected void onCreate(Bundle savedInstanceState) {
162        super.onCreate(savedInstanceState);
163        setContentView(R.layout.activity_screen_slide);
164
165        // Instantiate a ViewPager and a PagerAdapter.
166        mPager = (ViewPager) findViewById(R.id.pager);
167        mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
168        mPager.setAdapter(mPagerAdapter);
169    }
170
171    &#64;Override
172    public void onBackPressed() {
173        if (mPager.getCurrentItem() == 0) {
174            // If the user is currently looking at the first step, allow the system to handle the
175            // Back button. This calls finish() on this activity and pops the back stack.
176            super.onBackPressed();
177        } else {
178            // Otherwise, select the previous step.
179            mPager.setCurrentItem(mPager.getCurrentItem() - 1);
180        }
181    }
182
183    /**
184     * A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in
185     * sequence.
186     */
187    private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
188        public ScreenSlidePagerAdapter(FragmentManager fm) {
189            super(fm);
190        }
191
192        &#64;Override
193        public Fragment getItem(int position) {
194            return new ScreenSlidePageFragment();
195        }
196
197        &#64;Override
198        public int getCount() {
199            return NUM_PAGES;
200        }
201    }
202}
203</pre>
204
205
206<h2 id="pagetransformer">Customize the Animation with PageTransformer</h2>
207
208<p>To display a different animation from the default screen slide animation, implement the
209  {@link android.support.v4.view.ViewPager.PageTransformer} interface and supply it to
210  the view pager. The interface exposes a single method, {@link android.support.v4.view.ViewPager.PageTransformer#transformPage transformPage()}. At each point in the screen's transition, this method is called once for each visible page (generally there's only one visible page) and for adjacent pages just off the screen.
211  For example, if page three is visible and the user drags towards page four,
212  {@link android.support.v4.view.ViewPager.PageTransformer#transformPage transformPage()} is called
213  for pages two, three, and four at each step of the gesture.</p>
214
215  <p>
216  In your implementation of {@link android.support.v4.view.ViewPager.PageTransformer#transformPage transformPage()},
217  you can then create custom slide animations by determining which pages need to be transformed based on the
218  position of the page on the screen, which is obtained from the <code>position</code> parameter
219  of the {@link android.support.v4.view.ViewPager.PageTransformer#transformPage transformPage()} method.</p>
220
221<p>The <code>position</code> parameter indicates where a given page is located relative to the center of the screen.
222It is a dynamic property that changes as the user scrolls through the pages. When a page fills the screen, its position value is <code>0</code>.
223When a page is drawn just off the right side of the screen, its position value is <code>1</code>. If the user scrolls halfway between pages one and two, page one has a position of -0.5 and page two has a position of 0.5. Based on the position of the pages on the screen, you can create custom slide animations by setting page properties with methods such as {@link android.view.View#setAlpha setAlpha()}, {@link android.view.View#setTranslationX setTranslationX()}, or
224  {@link android.view.View#setScaleY setScaleY()}.</p>
225
226
227<p>When you have an implementation of a {@link android.support.v4.view.ViewPager.PageTransformer PageTransformer},
228call {@link android.support.v4.view.ViewPager#setPageTransformer setPageTransformer()} with
229  your implementation to apply your custom animations. For example, if you have a
230  {@link android.support.v4.view.ViewPager.PageTransformer PageTransformer} named
231  <code>ZoomOutPageTransformer</code>, you can set your custom animations
232  like this:</p>
233<pre>
234ViewPager mPager = (ViewPager) findViewById(R.id.pager);
235...
236mPager.setPageTransformer(true, new ZoomOutPageTransformer());
237</pre>
238
239
240<p>See the <a href="#zoom-out">Zoom-out page transformer</a> and <a href="#depth-page">Depth page transformer</a>
241sections for examples and videos of a {@link android.support.v4.view.ViewPager.PageTransformer PageTransformer}.</p>
242
243
244<h3 id="zoom-out">Zoom-out page transformer</h3>
245<p>
246 This page transformer shrinks and fades pages when scrolling between
247 adjacent pages. As a page gets closer to the center, it grows back to
248 its normal size and fades in.
249</p>
250
251<div class="framed-galaxynexus-land-span-8">
252  <video class="play-on-hover" autoplay>
253    <source src="anim_page_transformer_zoomout.mp4" type="video/mp4">
254    <source src="anim_page_transformer_zoomout.webm" type="video/webm">
255    <source src="anim_page_transformer_zoomout.ogv" type="video/ogg">
256  </video>
257</div>
258
259<div class="figure-caption">
260  <code>ZoomOutPageTransformer</code> example
261  <div class="video-instructions">&nbsp;</div>
262</div>
263
264
265<pre>
266public class ZoomOutPageTransformer implements ViewPager.PageTransformer {
267    private static final float MIN_SCALE = 0.85f;
268    private static final float MIN_ALPHA = 0.5f;
269
270    public void transformPage(View view, float position) {
271        int pageWidth = view.getWidth();
272        int pageHeight = view.getHeight();
273
274        if (position &lt; -1) { // [-Infinity,-1)
275            // This page is way off-screen to the left.
276            view.setAlpha(0);
277
278        } else if (position &lt;= 1) { // [-1,1]
279            // Modify the default slide transition to shrink the page as well
280            float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
281            float vertMargin = pageHeight * (1 - scaleFactor) / 2;
282            float horzMargin = pageWidth * (1 - scaleFactor) / 2;
283            if (position &lt; 0) {
284                view.setTranslationX(horzMargin - vertMargin / 2);
285            } else {
286                view.setTranslationX(-horzMargin + vertMargin / 2);
287            }
288
289            // Scale the page down (between MIN_SCALE and 1)
290            view.setScaleX(scaleFactor);
291            view.setScaleY(scaleFactor);
292
293            // Fade the page relative to its size.
294            view.setAlpha(MIN_ALPHA +
295                    (scaleFactor - MIN_SCALE) /
296                    (1 - MIN_SCALE) * (1 - MIN_ALPHA));
297
298        } else { // (1,+Infinity]
299            // This page is way off-screen to the right.
300            view.setAlpha(0);
301        }
302    }
303}
304</pre>
305
306<h3 id="depth-page">Depth page transformer</h3>
307<p>
308This page transformer uses the default slide animation for sliding pages
309to the left, while using a "depth" animation for sliding pages to the
310right. This depth animation fades the page out, and scales it down linearly.
311</p>
312
313<div class="framed-galaxynexus-land-span-8">
314  <video class="play-on-hover" autoplay>
315    <source src="anim_page_transformer_depth.mp4" type="video/mp4">
316    <source src="anim_page_transformer_depth.webm" type="video/webm">
317    <source src="anim_page_transformer_depth.ogv" type="video/ogg">
318  </video>
319</div>
320
321<div class="figure-caption">
322  <code>DepthPageTransformer</code> example
323  <div class="video-instructions">&nbsp;</div>
324</div>
325
326<p class="note"><strong>Note:</strong> During the depth animation, the default animation (a screen slide) still
327takes place, so you must counteract the screen slide with a negative X translation.
328
329For example:
330
331<pre>
332view.setTranslationX(-1 * view.getWidth() * position);
333</pre>
334
335The following example shows how to counteract the default screen slide animation
336in a working page transformer:
337</p>
338
339<pre>
340
341public class DepthPageTransformer implements ViewPager.PageTransformer {
342    private static final float MIN_SCALE = 0.75f;
343
344    public void transformPage(View view, float position) {
345        int pageWidth = view.getWidth();
346
347        if (position &lt; -1) { // [-Infinity,-1)
348            // This page is way off-screen to the left.
349            view.setAlpha(0);
350
351        } else if (position &lt;= 0) { // [-1,0]
352            // Use the default slide transition when moving to the left page
353            view.setAlpha(1);
354            view.setTranslationX(0);
355            view.setScaleX(1);
356            view.setScaleY(1);
357
358        } else if (position &lt;= 1) { // (0,1]
359            // Fade the page out.
360            view.setAlpha(1 - position);
361
362            // Counteract the default slide transition
363            view.setTranslationX(pageWidth * -position);
364
365            // Scale the page down (between MIN_SCALE and 1)
366            float scaleFactor = MIN_SCALE
367                    + (1 - MIN_SCALE) * (1 - Math.abs(position));
368            view.setScaleX(scaleFactor);
369            view.setScaleY(scaleFactor);
370
371        } else { // (1,+Infinity]
372            // This page is way off-screen to the right.
373            view.setAlpha(0);
374        }
375    }
376}
377</pre>
378
379