注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好。

原文链接:http://developer.android.com/training/animation/screen-slide.html


屏幕滑动是从一个完整的屏幕转换到另一个屏幕的动画,对于配置向导或者幻灯片的应用场景是很常见的。这节课将会展示如何使用support library.ViewPager提供的ViewPager来自动实现滑动的动画。下面是一个屏幕滑动的动画例子:

屏幕滑动动画

如果你希望略过这部分内容直接看代码样例,可以直接下载样例代码,然后选择淡入淡出动画的例子。下面的文件是实现代码:

  • src/ScreenSlidePageFragment.java
  • src/ScreenSlideActivity.java
  • layout/activity_screen_slide.xml
  • layout/fragment_screen_slide_page.xml

一). 创建视图

创建一个布局文件,你马上就会使用到它作为一个fragment的内容布局。下面的代码是一个例子,包含了一个文本框显示一些文本:

  1. <!-- fragment_screen_slide_page.xml -->
  2. <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:id="@+id/content"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent" >
  6.  
  7. <TextView style="?android:textAppearanceMedium"
  8. android:padding="16dp"
  9. android:lineSpacingMultiplier="1.2"
  10. android:layout_width="match_parent"
  11. android:layout_height="wrap_content"
  12. android:text="@string/lorem_ipsum" />
  13. </ScrollView>

同时记得给这个fragment定义一个字符串。


二). 创建一个Fragment

创建一个Fragment类,在onCreateView()中返回你刚才创建的布局。当你需要向用户显示新的一页时,你可以之后在父activity中创建这个fragment的实例:

  1. import android.support.v4.app.Fragment;
  2. ...
  3. public class ScreenSlidePageFragment extends Fragment {
  4.  
  5. @Override
  6. public View onCreateView(LayoutInflater inflater, ViewGroup container,
  7. Bundle savedInstanceState) {
  8. ViewGroup rootView = (ViewGroup) inflater.inflate(
  9. R.layout.fragment_screen_slide_page, container, false);
  10.  
  11. return rootView;
  12. }
  13. }

三). 添加一个ViewPager

ViewPager拥有内置的页面间滑动手势并且默认是显示滑动动画的,所以你不需要创建任何动画。 ViewPager使用PagerAdapter作为一个要显示的新页面的提供者,所以PagerAdapter会使用你之前创建的fragment类。

首先,创建一个包含ViewPager的布局:

  1. <!-- activity_screen_slide.xml -->
  2. <android.support.v4.view.ViewPager
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:id="@+id/pager"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent" />

创建一个activity,它完成下列事情:

  • 将视图的布局设置为包含了ViewPager的布局。
  • 创建一个继承FragmentStatePagerAdapter抽象类的类,并且实现getItem()方法来提供ScreenSlidePageFragment的实例作为新的页面。这个页面适配器(Pager Adapter)还要求你实现getCount()方法,它返回适配器需要创建的页面数量(比如说有五页)。
  • PagerAdapterViewPager关联起来。
  • 处理设备的后退按键,让它实现在虚拟堆栈中向后移动。如果用户已经在第一页了,回到activity的后退堆栈。
  1. import android.support.v4.app.Fragment;
  2. import android.support.v4.app.FragmentManager;
  3. ...
  4. public class ScreenSlidePagerActivity extends FragmentActivity {
  5. /**
  6. * The number of pages (wizard steps) to show in this demo.
  7. */
  8. private static final int NUM_PAGES = 5;
  9.  
  10. /**
  11. * The pager widget, which handles animation and allows swiping horizontally to access previous
  12. * and next wizard steps.
  13. */
  14. private ViewPager mPager;
  15.  
  16. /**
  17. * The pager adapter, which provides the pages to the view pager widget.
  18. */
  19. private PagerAdapter mPagerAdapter;
  20.  
  21. @Override
  22. protected void onCreate(Bundle savedInstanceState) {
  23. super.onCreate(savedInstanceState);
  24. setContentView(R.layout.activity_screen_slide);
  25.  
  26. // Instantiate a ViewPager and a PagerAdapter.
  27. mPager = (ViewPager) findViewById(R.id.pager);
  28. mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
  29. mPager.setAdapter(mPagerAdapter);
  30. }
  31.  
  32. @Override
  33. public void onBackPressed() {
  34. if (mPager.getCurrentItem() == 0) {
  35. // If the user is currently looking at the first step, allow the system to handle the
  36. // Back button. This calls finish() on this activity and pops the back stack.
  37. super.onBackPressed();
  38. } else {
  39. // Otherwise, select the previous step.
  40. mPager.setCurrentItem(mPager.getCurrentItem() - 1);
  41. }
  42. }
  43.  
  44. /**
  45. * A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in
  46. * sequence.
  47. */
  48. private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
  49. public ScreenSlidePagerAdapter(FragmentManager fm) {
  50. super(fm);
  51. }
  52.  
  53. @Override
  54. public Fragment getItem(int position) {
  55. return new ScreenSlidePageFragment();
  56. }
  57.  
  58. @Override
  59. public int getCount() {
  60. return NUM_PAGES;
  61. }
  62. }
  63. }

二). 通过PageTransformer自定义动画

要显示一个与默认的滑动屏幕动画不同的动画,需要实现ViewPager.PageTransformer接口,并将它提供给ViewPager。该接口有一个共有方法:transformPage()。每次屏幕切换,该方法都会为每一个可见的页面(一般来说都只有一个可见页面)及相邻的离开屏幕范围的页面执行一次。例如,如果当前第三页是可见的,并且用户滑动到了第四页,那么transformPage()方法会在手势执行的过程中,分别为第二页,第三页和第四页进行调用。

在你的transformPage()的实现中,你可以根据当前屏幕所显示的页的位置,确定哪些页需要变化,创建自定义的滑动动画,着可以通过transformPage()方法的position参数获得。

position变量指出了某个页面相对于中心的位置。这个变量会随着用户在页面间切换而动态变化。当一个页面充满屏幕时,它的position值是0。当一个页面被拉出到了屏幕右侧,它的position值是1。如果用户在页面一和页面二切换过程中,那么页面一的position值为-0.5,页面二的position值为0.5。根据页面对于屏幕的位置,你可以通过设置页面的属性,比如:setAlpha()setTranslationX()setScaleY(),来创建自定义的滑动动画。

当你有一个PageTransformer的实现,在你的实现中调用setPageTransformer()来应用你的自定义动画。例如,如果你有一个叫ZoomOutPageTransformerPageTransformer,你可以这样设置你的自定义动画:

  1. ViewPager mPager = (ViewPager) findViewById(R.id.pager);
  2. ...
  3. mPager.setPageTransformer(true, new ZoomOutPageTransformer());

拉远页面切换(Zoom-out)

这个动画会缩小页面然后在滑动过程中淡化相邻的页面。在一个页面接近中心的时候,它会回到它的标准大小并且淡入。

Zoom-out动画

  1. public class ZoomOutPageTransformer implements ViewPager.PageTransformer {
  2. private static final float MIN_SCALE = 0.85f;
  3. private static final float MIN_ALPHA = 0.5f;
  4.  
  5. public void transformPage(View view, float position) {
  6. int pageWidth = view.getWidth();
  7. int pageHeight = view.getHeight();
  8.  
  9. if (position < -1) { // [-Infinity,-1)
  10. // This page is way off-screen to the left.
  11. view.setAlpha(0);
  12.  
  13. } else if (position <= 1) { // [-1,1]
  14. // Modify the default slide transition to shrink the page as well
  15. float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
  16. float vertMargin = pageHeight * (1 - scaleFactor) / 2;
  17. float horzMargin = pageWidth * (1 - scaleFactor) / 2;
  18. if (position < 0) {
  19. view.setTranslationX(horzMargin - vertMargin / 2);
  20. } else {
  21. view.setTranslationX(-horzMargin + vertMargin / 2);
  22. }
  23.  
  24. // Scale the page down (between MIN_SCALE and 1)
  25. view.setScaleX(scaleFactor);
  26. view.setScaleY(scaleFactor);
  27.  
  28. // Fade the page relative to its size.
  29. view.setAlpha(MIN_ALPHA +
  30. (scaleFactor - MIN_SCALE) /
  31. (1 - MIN_SCALE) * (1 - MIN_ALPHA));
  32.  
  33. } else { // (1,+Infinity]
  34. // This page is way off-screen to the right.
  35. view.setAlpha(0);
  36. }
  37. }
  38. }

深度页面动画(Depth) 

这个动画对于向左滑动的页面使用默认的滑动动画,而对于从右侧滑入的页面使用深度动画。该动画淡出页面,并且线性地缩小它的大小。

Depth动画

Note:

在深度动画过程中,默认的动画(屏幕滑动)仍然发生,所以你必须用一个负X方向来抵消屏幕滑动,例如

  1. view.setTranslationX(-1 * view.getWidth() * position);

下面的例子展示了如何在一个工作页面中,抵消默认的屏幕滑动动画:

  1. public class DepthPageTransformer implements ViewPager.PageTransformer {
  2. private static final float MIN_SCALE = 0.75f;
  3.  
  4. public void transformPage(View view, float position) {
  5. int pageWidth = view.getWidth();
  6.  
  7. if (position < -1) { // [-Infinity,-1)
  8. // This page is way off-screen to the left.
  9. view.setAlpha(0);
  10.  
  11. } else if (position <= 0) { // [-1,0]
  12. // Use the default slide transition when moving to the left page
  13. view.setAlpha(1);
  14. view.setTranslationX(0);
  15. view.setScaleX(1);
  16. view.setScaleY(1);
  17.  
  18. } else if (position <= 1) { // (0,1]
  19. // Fade the page out.
  20. view.setAlpha(1 - position);
  21.  
  22. // Counteract the default slide transition
  23. view.setTranslationX(pageWidth * -position);
  24.  
  25. // Scale the page down (between MIN_SCALE and 1)
  26. float scaleFactor = MIN_SCALE
  27. + (1 - MIN_SCALE) * (1 - Math.abs(position));
  28. view.setScaleX(scaleFactor);
  29. view.setScaleY(scaleFactor);
  30.  
  31. } else { // (1,+Infinity]
  32. // This page is way off-screen to the right.
  33. view.setAlpha(0);
  34. }
  35. }
  36. }

【Android Developers Training】 70. 使用ViewPager实现屏幕滑动的更多相关文章

  1. 【Android Developers Training】 12. 支持不同屏幕

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  2. 【Android Developers Training】 68. 序言:添加动画

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  3. 【Android Developers Training】 10. 序言:支持不同设备

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  4. 【Android Developers Training】 60. 在你的UI中显示位图

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  5. 【Android Developers Training】 58. 缓存位图

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  6. 【Android Developers Training】 55. 序言:高效显示位图

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  7. 【Android Developers Training】 9. 覆盖于布局之上的Action Bar

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  8. 【Android Developers Training】 7. 添加Action Buttons

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  9. 【Android Developers Training】 4. 启动另一个Activity

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

随机推荐

  1. 简单的记录,VMware Tools的安装

    VMware Tools是VMware虚拟机中自带的一种增强工具,只有在VMware虚拟机中安装好了VMware Tools,才能实现主机与虚拟机之间的文件共享,同时可支持自由“拖拽”的功能来对传文件 ...

  2. 全景智慧城市——NOW!!!VRSHOPPING颠覆你的购物认知!

    互联网+时代,人们对现有的网络资源已经不再感冒,一般的图片.文字信息已经无法满足人们对互联网的需求,虚拟现实.身临其境的体验是不可小觑的发展趋势,尤其是VR逛街.购物,更会深入人心,再次改变人们的生活 ...

  3. asp.net Socket的简单Web Server

    1.首先初始化socket,包含对端点以及对连接队列长度的初始化 IPAddress address = IPAddress.Loopback; IPEndPoint endPoint = ); So ...

  4. 深入理解Struts2----类型转换

         之前的一系列文章主要介绍了有关Struts2的一些基本用法和部分的简单原理,但是始终没有介绍有关拦截器的相关内容,从本篇开始我们将从另一个角度去深入理解框架的使用,核心还是拦截器,但本篇首先 ...

  5. 写给Android App开发人员看的Android底层知识(1)

    这个系列的文章一共8篇,我酝酿了很多年,参考了很多资源,查看了很多源码,直到今天把它写出来,也是战战兢兢,生怕什么地方写错了,贻笑大方. (一)引言 早在我还是Android菜鸟的时候,有很多技术我都 ...

  6. 数据结构与算法系列研究七——图、prim算法、dijkstra算法

    图.prim算法.dijkstra算法 1. 图的定义 图(Graph)可以简单表示为G=<V, E>,其中V称为顶点(vertex)集合,E称为边(edge)集合.图论中的图(graph ...

  7. 微信小程序demo

    微信小程序demo github地址 去年小程序刚发布时特别火,赶潮流做了个demo.感觉小程序开发还是比较简单的,主要是官方文档写得比较好,遗憾的是很多API需要微信认证才能使用. 由于小程序包大小 ...

  8. Java基础知识二次学习--第五章 数组

    第五章 数组 时间:2017年4月26日15:11:30~2017年4月26日15:15:54 章节:05章_01节  视频长度:09:30 内容:一维数组的内存分析 心得: Java中数组是引用类型 ...

  9. Selenium 高阶应用之WebDriverWait 和 expected_conditions

    Seleniium 是相当不错的一个第三方测试框架,可惜目前国内已经无法访问其官网(FQ可以). 不知道大家是否有认真查看过selenium 的api,我是有认真学习过的.selenium 的api中 ...

  10. aws上redhat安装lmysql服务记

    aws上redhat安装lmysql服务记 1.准备材料 1.1