Home | History | Annotate | Download | only in animation
      1 page.title=Using ViewPager for Screen Slides
      2 trainingnavtop=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>
     52 and run the sample app and select the Screen Slide example. See the
     53 following 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;com.example.android.animationsdemo.ScrollView
     67     xmlns:android="http://schemas.android.com/apk/res/android"
     68     android:id="@+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 
     79 &lt;/com.example.android.animationsdemo.ScrollView&gt;
     80 </pre>
     81 
     82 <h2 id="fragment">Create the Fragment</h2>
     83 <p>Create a {@link android.support.v4.app.Fragment} class that returns the layout
     84 that you just created in the {@link android.app.Fragment#onCreateView onCreateView()}
     85   method. You can then create instances of this fragment in the parent activity whenever you need a new page to
     86   display to the user:</p>
     87 
     88 
     89 <pre>
     90 public class ScreenSlidePageFragment extends Fragment {
     91 
     92     &#64;Override
     93     public View onCreateView(LayoutInflater inflater, ViewGroup container,
     94             Bundle savedInstanceState) {
     95         ViewGroup rootView = (ViewGroup) inflater.inflate(
     96                 R.layout.fragment_screen_slide_page, container, false);
     97 
     98         return rootView;
     99     }
    100 }
    101 </pre>
    102 
    103 <h2 id="viewpager">Add a ViewPager</h2>
    104 
    105 <p>{@link android.support.v4.view.ViewPager}s have built-in swipe gestures to transition
    106   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
    107 {@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
    108 fragment class that you created earlier.
    109   </p>
    110 
    111 <p>To begin, create a layout that contains a {@link android.support.v4.view.ViewPager}:</p>
    112 
    113 <pre>
    114 &lt;android.support.v4.view.ViewPager
    115     xmlns:android="http://schemas.android.com/apk/res/android"
    116     android:id="@+id/pager"
    117     android:layout_width="match_parent"
    118     android:layout_height="match_parent" /&gt;
    119 </pre>
    120 
    121 <p>Create an activity that does the following things:
    122 </p>
    123 
    124 <ul>
    125   <li>Sets the content view to be the layout with the {@link android.support.v4.view.ViewPager}.</li>
    126   <li>Creates a class that extends the {@link android.support.v13.app.FragmentStatePagerAdapter} abstract class and implements
    127   the {@link android.support.v4.app.FragmentStatePagerAdapter#getItem getItem()} method to supply
    128     instances of <code>ScreenSlidePageFragment</code> as new pages. The pager adapter also requires that you implement the
    129     {@link android.support.v4.view.PagerAdapter#getCount getCount()} method, which returns the amount of pages the adapter will create (five in the example).
    130   <li>Hooks up the {@link android.support.v4.view.PagerAdapter} to the {@link android.support.v4.view.ViewPager}</code>.</li>
    131   <li>Handles the device's back button by moving backwards in the virtual stack of fragments.
    132     If the user is already on the first page, go back on the activity back stack.</li>
    133 </ul>
    134 
    135 <pre>
    136 public class ScreenSlidePagerActivity extends FragmentActivity {
    137     /**
    138      * The number of pages (wizard steps) to show in this demo.
    139      */
    140     private static final int NUM_PAGES = 5;
    141 
    142     /**
    143      * The pager widget, which handles animation and allows swiping horizontally to access previous
    144      * and next wizard steps.
    145      */
    146     private ViewPager mPager;
    147 
    148     /**
    149      * The pager adapter, which provides the pages to the view pager widget.
    150      */
    151     private PagerAdapter mPagerAdapter;
    152 
    153     &#64;Override
    154     protected void onCreate(Bundle savedInstanceState) {
    155         super.onCreate(savedInstanceState);
    156         setContentView(R.layout.activity_screen_slide_pager);
    157 
    158         // Instantiate a ViewPager and a PagerAdapter.
    159         mPager = (ViewPager) findViewById(R.id.pager);
    160         mPagerAdapter = new ScreenSlidePagerAdapter(getFragmentManager());
    161         mPager.setAdapter(mPagerAdapter);
    162     }
    163 
    164     &#64;Override
    165     public void onBackPressed() {
    166         if (mPager.getCurrentItem() == 0) {
    167             // If the user is currently looking at the first step, allow the system to handle the
    168             // Back button. This calls finish() on this activity and pops the back stack.
    169             super.onBackPressed();
    170         } else {
    171             // Otherwise, select the previous step.
    172             mPager.setCurrentItem(mPager.getCurrentItem() - 1);
    173         }
    174     }
    175 
    176     /**
    177      * A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in
    178      * sequence.
    179      */
    180     private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
    181         public ScreenSlidePagerAdapter(FragmentManager fm) {
    182             super(fm);
    183         }
    184 
    185         &#64;Override
    186         public Fragment getItem(int position) {
    187             return new ScreenSlidePageFragment();
    188         }
    189 
    190         &#64;Override
    191         public int getCount() {
    192             return NUM_PAGES;
    193         }
    194     }
    195 }
    196 </pre>
    197 
    198 
    199 <h2 id="pagetransformer">Customize the Animation with PageTransformer</h2>
    200 
    201 <p>To display a different animation from the default screen slide animation, implement the
    202   {@link android.support.v4.view.ViewPager.PageTransformer} interface and supply it to
    203   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.
    204   For example, if page three is visible and the user drags towards page four,
    205   {@link android.support.v4.view.ViewPager.PageTransformer#transformPage transformPage()} is called
    206   for pages two, three, and four at each step of the gesture.</p>
    207 
    208   <p>
    209   In your implementation of {@link android.support.v4.view.ViewPager.PageTransformer#transformPage transformPage()},
    210   you can then create custom slide animations by determining which pages need to be transformed based on the
    211   position of the page on the screen, which is obtained from the <code>position</code> parameter
    212   of the {@link android.support.v4.view.ViewPager.PageTransformer#transformPage transformPage()} method.</p>
    213 
    214 <p>The <code>position</code> parameter indicates where a given page is located relative to the center of the screen. 
    215 It 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>.
    216 When 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
    217   {@link android.view.View#setScaleY setScaleY()}.</p>
    218 
    219 
    220 <p>When you have an implementation of a {@link android.support.v4.view.ViewPager.PageTransformer PageTransformer},
    221 call {@link android.support.v4.view.ViewPager#setPageTransformer setPageTransformer()} with
    222   your implementation to apply your custom animations. For example, if you have a
    223   {@link android.support.v4.view.ViewPager.PageTransformer PageTransformer} named
    224   <code>ZoomOutPageTransformer</code>, you can set your custom animations
    225   like this:</p>
    226 <pre>
    227 ViewPager pager = (ViewPager) findViewById(R.id.pager);
    228 ...
    229 pager.setPageTransformer(true, new ZoomOutPageTransformer());
    230 </pre>
    231 
    232 
    233 <p>See the <a href="#zoom-out">Zoom-out page transformer</a> and <a href="#depth-page">Depth page transformer</a>
    234 sections for examples and videos of a {@link android.support.v4.view.ViewPager.PageTransformer PageTransformer}.</p>
    235 
    236 
    237 <h3 id="zoom-out">Zoom-out page transformer</h3>
    238 <p>
    239  This page transformer shrinks and fades pages when scrolling between
    240  adjacent pages. As a page gets closer to the center, it grows back to
    241  its normal size and fades in.
    242 </p>
    243 
    244 <div class="framed-galaxynexus-land-span-8">
    245   <video class="play-on-hover" autoplay>
    246     <source src="anim_page_transformer_zoomout.mp4" type="video/mp4">
    247     <source src="anim_page_transformer_zoomout.webm" type="video/webm">
    248     <source src="anim_page_transformer_zoomout.ogv" type="video/ogg">
    249   </video>
    250 </div>
    251 
    252 <div class="figure-caption">
    253   <code>ZoomOutPageTransformer</code> example
    254   <div class="video-instructions">&nbsp;</div>
    255 </div>
    256 
    257 
    258 <pre>
    259 public class ZoomOutPageTransformer implements ViewPager.PageTransformer {
    260     private static float MIN_SCALE = 0.85f;
    261     private static float MIN_ALPHA = 0.5f;
    262 
    263     public void transformPage(View view, float position) {
    264         int pageWidth = view.getWidth();
    265         int pageHeight = view.getHeight();
    266 
    267         if (position &lt; -1) { // [-Infinity,-1)
    268             // This page is way off-screen to the left.
    269             view.setAlpha(0);
    270 
    271         } else if (position &lt;= 1) { // [-1,1]
    272             // Modify the default slide transition to shrink the page as well
    273             float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
    274             float vertMargin = pageHeight * (1 - scaleFactor) / 2;
    275             float horzMargin = pageWidth * (1 - scaleFactor) / 2;
    276             if (position &lt; 0) {
    277                 view.setTranslationX(horzMargin - vertMargin / 2);
    278             } else {
    279                 view.setTranslationX(-horzMargin + vertMargin / 2);
    280             }
    281 
    282             // Scale the page down (between MIN_SCALE and 1)
    283             view.setScaleX(scaleFactor);
    284             view.setScaleY(scaleFactor);
    285 
    286             // Fade the page relative to its size.
    287             view.setAlpha(MIN_ALPHA +
    288                     (scaleFactor - MIN_SCALE) /
    289                     (1 - MIN_SCALE) * (1 - MIN_ALPHA));
    290 
    291         } else { // (1,+Infinity]
    292             // This page is way off-screen to the right.
    293             view.setAlpha(0);
    294         }
    295     }
    296 }
    297 </pre>
    298 
    299 <h3 id="depth-page">Depth page transformer</h3>
    300 <p>
    301 This page transformer uses the default slide animation for sliding pages
    302 to the left, while using a "depth" animation for sliding pages to the
    303 right. This depth animation fades the page out, and scales it down linearly.
    304 </p>
    305 
    306 <div class="framed-galaxynexus-land-span-8">
    307   <video class="play-on-hover" autoplay>
    308     <source src="anim_page_transformer_depth.mp4" type="video/mp4">
    309     <source src="anim_page_transformer_depth.webm" type="video/webm">
    310     <source src="anim_page_transformer_depth.ogv" type="video/ogg">
    311   </video>
    312 </div>
    313 
    314 <div class="figure-caption">
    315   <code>DepthPageTransformer</code> example
    316   <div class="video-instructions">&nbsp;</div>
    317 </div>
    318 
    319 <p class="note"><strong>Note:</strong> During the depth animation, the default animation (a screen slide) still
    320 takes place, so you must counteract the screen slide with a negative X translation.
    321 
    322 For example:
    323 
    324 <pre>
    325 view.setTranslationX(-1 * view.getWidth() * position);
    326 </pre>
    327 
    328 The following example shows how to counteract the default screen slide animation
    329 in a working page transformer:
    330 </p>
    331 
    332 <pre>
    333 
    334 public class DepthPageTransformer implements ViewPager.PageTransformer {
    335     private static float MIN_SCALE = 0.75f;
    336 
    337     public void transformPage(View view, float position) {
    338         int pageWidth = view.getWidth();
    339 
    340         if (position &lt; -1) { // [-Infinity,-1)
    341             // This page is way off-screen to the left.
    342             view.setAlpha(0);
    343 
    344         } else if (position &lt;= 0) { // [-1,0]
    345             // Use the default slide transition when moving to the left page
    346             view.setAlpha(1);
    347             view.setTranslationX(0);
    348             view.setScaleX(1);
    349             view.setScaleY(1);
    350 
    351         } else if (position &lt;= 1) { // (0,1]
    352             // Fade the page out.
    353             view.setAlpha(1 - position);
    354 
    355             // Counteract the default slide transition
    356             view.setTranslationX(pageWidth * -position);
    357 
    358             // Scale the page down (between MIN_SCALE and 1)
    359             float scaleFactor = MIN_SCALE
    360                     + (1 - MIN_SCALE) * (1 - Math.abs(position));
    361             view.setScaleX(scaleFactor);
    362             view.setScaleY(scaleFactor);
    363 
    364         } else { // (1,+Infinity]
    365             // This page is way off-screen to the right.
    366             view.setAlpha(0);
    367         }
    368     }
    369 }
    370 </pre>
    371 
    372