是指从从一个完整屏幕到另一个屏幕的转移过渡,经常用在app安装向导或者幻灯片展示上。本节课讲解如何用ViewPage实现屏幕幻灯片,支持库ViewPager能够自动实现屏幕幻灯片效果。
创建View
创建一个用于fragment的layout布局文件。如下示例布局文件包含一个text view来显示某些文字。
<com.example.android.animationsdemo.ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/content" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView style="?android:textAppearanceMedium" android:padding="16dp" android:lineSpacingMultiplier="1.2" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/lorem_ipsum" /> </com.example.android.animationsdemo.ScrollView>
创建Fragment片段
创建一个Fragment类,在onCreateView()方法中返回你刚刚创建的layout布局。任何时候你想显示一个新的页面给用户时,你就可以在父activity中创建这个Fragment的实例:
public class ScreenSlidePageFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ViewGroup rootView = (ViewGroup) inflater.inflate( R.layout.fragment_screen_slide_page, container, false); return rootView; } }
添加一个ViewPager
ViewPager
s 有内置的滑动手势功能,通过滑动在多个page之间转移,屏幕幻灯片动画的显示是其默认方式,所以你不需要以PagerAdapter创建任何.ViewPager,不需要以PagerAdapter作为新的pager的提供者,也不需要PagerAdapter使用先前创造的fragment类。have built-in swipe gestures to transition through pages, and they display screen slide animations by default, so you don't need to create any. ViewPager
s use PagerAdapter
s as a supply for new pages to display, so the PagerAdapter
will use the fragment class that you created earlier.
首先,创造一个包含ViewPager的layout布局。
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent" />
创建一个activity,该activity做以下几件事情:
- 将ViewPager设置为activity的显示内容
- 创建一个继承
FragmentStatePagerAdapter
抽象类的类并实现getItem()方法,这个方法
提供ScreenSlidePageFragment
的实例作为新的page页。Pager Adapter作为ViewPager的适配器,需要实现getCount()方法,这个方法返回适配器中的页面数(本例子中为5)。 - 把
PagerAdapter
绑定到ViewPager
. - 处理设备的回退键事件响应,当回退键按下时,在fragment片段的虚拟堆栈中做回退操作。如果用户已经在第一页了,那么继续在activity的回退栈中做回退。
public class ScreenSlidePagerActivity extends FragmentActivity { /** * 页面的个数(向导的步数) */ private static final int NUM_PAGES = 5; /** * Pager组件,可以水平滑动来访问上一个向导步骤或者下一个。 */ private ViewPager mPager; /** * Pager Adapter适配器,给view pager组件提供页面。 */ private PagerAdapter mPagerAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_screen_slide_pager); // 实例化一个ViewPager和PagerAdapter. mPager = (ViewPager) findViewById(R.id.pager); mPagerAdapter = new ScreenSlidePagerAdapter(getFragmentManager()); mPager.setAdapter(mPagerAdapter); } @Override public void onBackPressed() { if (mPager.getCurrentItem() == 0) { // 如果当前用户正在看向导的第一步,那么让系统来处理这个后退键好了,系统会调用这个activity的finish()然后对回退栈做弹出操作。 super.onBackPressed(); } else { // 否则的话,选择回退到上一步 mPager.setCurrentItem(mPager.getCurrentItem() - 1); } } /** * 简单的Pager Adapter,按顺序显示五个ScreenSlidePageFragment。 */ private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter { public ScreenSlidePagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { return new ScreenSlidePageFragment(); } @Override public int getCount() { return NUM_PAGES; } } }
通过PageTransformer自定义动画
如果不想按默认的屏幕幻灯片动画,那么需要实现ViewPager.PagerTransformer接口,然后把实现提供给viewPager。这个接口只有一个方法,就是transformPage()。在每次屏幕转移的那一时点,这个方法会被调用一次,一是为了每个当前处于visible状态的page页面(一般情况下只有一个是visible的),二是为了刚刚离开屏幕的相邻页面。例如,如果页面三是visible的,而用户向页面四做滑动董卓,transformPage()方法会为页面二、三、四调用。
position参数指出了相对于屏幕中心,给定页面的相对位置。这是一个动态的参数,会随着用户滑动页面而改变。当一个页面填满屏幕时,他的位置是0。当一个页面刚刚被滑出到屏幕的右侧时,他的位置是1.当用户把页面1和页面2滑动到屏幕中间时,页面1和页面2各占屏幕一部分,这时页面1的position为-0.5,页面2的position为0.5。基于页面在屏幕的相对位置,你可以通过设置页面的属性来创建个性化的屏幕幻灯片效果,可以通过像 setAlpha()
, setTranslationX()
, 或是 setScaleY()的方法来改变页面的属性。
当你实现了一个PageTransformer时,调用setPageTransformer()来实现个性化的幻灯片效果。如下所以,如果你有一个名为ZoomOutPageTransformer
的PageTransformer,你可以这样来设置个性化的幻灯片:
ViewPager pager = (ViewPager) findViewById(R.id.pager); ... pager.setPageTransformer(true, new ZoomOutPageTransformer());
下面是缩放型page transformer和深度型page transformer。
缩放型Zoom-out page transformer
当在相邻页面间滑动时,该pageTransformer会收缩和渐隐页面。当页面回到屏幕中心,它会放大页面尺寸然后渐现页面。
ZoomOutPageTransformer
example
public class ZoomOutPageTransformer implements ViewPager.PageTransformer { private static float MIN_SCALE = 0.85f; private static float MIN_ALPHA = 0.5f; public void transformPage(View view, float position) { int pageWidth = view.getWidth(); int pageHeight = view.getHeight(); if (position < -1) { // [-Infinity,-1) // 这个页面正在向左远离屏幕 view.setAlpha(0); } else if (position <= 1) { // [-1,1] // 修改默认幻灯片动画,缩小页面 float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position)); float vertMargin = pageHeight * (1 - scaleFactor) / 2; float horzMargin = pageWidth * (1 - scaleFactor) / 2; if (position < 0) { view.setTranslationX(horzMargin - vertMargin / 2); } else { view.setTranslationX(-horzMargin + vertMargin / 2); } // 按比例缩小页面(比例在 MIN_SCALE 和 1之间) view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); // 相对于其尺寸进行渐隐 view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA)); } else { // (1,+Infinity] // 该页面正在向右远离屏幕 view.setAlpha(0); } } }
深度型Depth page transformer
这个page transformer使用默认的屏幕幻灯片动画效果,同时用一个“加深”动画来作用于滑动到右边的页面。这个“加深”动画还慢慢渐隐页面,线性的缩小图片。
注意:D在使用“加深”动画的同时,默认的动画效果还仍然在,所以你必须用一个负的x轴偏移来抵消屏幕滑动。
view.setTranslationX(-1 * view.getWidth() * position);The following example shows how to counteract the default screen slide animation in a working page transformer:
public class DepthPageTransformer implements ViewPager.PageTransformer { private static float MIN_SCALE = 0.75f; public void transformPage(View view, float position) { int pageWidth = view.getWidth(); if (position < -1) { // [-Infinity,-1) // 页面正在向左离开屏幕 view.setAlpha(0); } else if (position <= 0) { // [-1,0] // 使用正常的滑动效果, view.setAlpha(1); view.setTranslationX(0); view.setScaleX(1); view.setScaleY(1); } else if (position <= 1) { // (0,1] // 渐隐 view.setAlpha(1 - position); // 抵消默认的滑动 view.setTranslationX(pageWidth * -position); // 按比例缩小图片 float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position)); view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); } else { // (1,+Infinity] // 页面向右离开屏幕 view.setAlpha(0); } } }