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/extras/support-library.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<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"> 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 79</com.example.android.animationsdemo.ScrollView> 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 84that 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> 90public class ScreenSlidePageFragment extends Fragment { 91 92 @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 108fragment 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<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" /> 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> 136public 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 @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 @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 @Override 186 public Fragment getItem(int position) { 187 return new ScreenSlidePageFragment(); 188 } 189 190 @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. 215It 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>. 216When 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}, 221call {@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> 227ViewPager pager = (ViewPager) findViewById(R.id.pager); 228... 229pager.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> 234sections 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"> </div> 255</div> 256 257 258<pre> 259public 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 < -1) { // [-Infinity,-1) 268 // This page is way off-screen to the left. 269 view.setAlpha(0); 270 271 } else if (position <= 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 < 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> 301This page transformer uses the default slide animation for sliding pages 302to the left, while using a "depth" animation for sliding pages to the 303right. 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"> </div> 317</div> 318 319<p class="note"><strong>Note:</strong> During the depth animation, the default animation (a screen slide) still 320takes place, so you must counteract the screen slide with a negative X translation. 321 322For example: 323 324<pre> 325view.setTranslationX(-1 * view.getWidth() * position); 326</pre> 327 328The following example shows how to counteract the default screen slide animation 329in a working page transformer: 330</p> 331 332<pre> 333 334public 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 < -1) { // [-Infinity,-1) 341 // This page is way off-screen to the left. 342 view.setAlpha(0); 343 344 } else if (position <= 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 <= 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