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;!-- 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
     85 that 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>
     91 import android.support.v4.app.Fragment;
     92 ...
     93 public 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
    111 fragment 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>
    140 import android.support.v4.app.Fragment;
    141 import android.support.v4.app.FragmentManager;
    142 ...
    143 public 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.
    222 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>.
    223 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
    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},
    228 call {@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>
    234 ViewPager mPager = (ViewPager) findViewById(R.id.pager);
    235 ...
    236 mPager.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>
    241 sections 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>
    266 public 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>
    308 This page transformer uses the default slide animation for sliding pages
    309 to the left, while using a "depth" animation for sliding pages to the
    310 right. 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
    327 takes place, so you must counteract the screen slide with a negative X translation.
    328 
    329 For example:
    330 
    331 <pre>
    332 view.setTranslationX(-1 * view.getWidth() * position);
    333 </pre>
    334 
    335 The following example shows how to counteract the default screen slide animation
    336 in a working page transformer:
    337 </p>
    338 
    339 <pre>
    340 
    341 public 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