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"> </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<!-- fragment_screen_slide_page.xml --> 67<ScrollView 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" > 71 72 <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" /> 78</ScrollView> 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 @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<!-- activity_screen_slide.xml --> 118<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" /> 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 @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 @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 @Override 193 public Fragment getItem(int position) { 194 return new ScreenSlidePageFragment(); 195 } 196 197 @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"> </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 < -1) { // [-Infinity,-1) 275 // This page is way off-screen to the left. 276 view.setAlpha(0); 277 278 } else if (position <= 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 < 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"> </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 < -1) { // [-Infinity,-1) 348 // This page is way off-screen to the left. 349 view.setAlpha(0); 350 351 } else if (position <= 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 <= 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