本文没有提供酷炫的动画实现,而是分析理解如何使用自定义
PageTransformer
完成要想的效果。
1、PageTransformer之position分析
从3.0开始,ViewPager开始支持自定义切换动画,官方提供的接口为PageTransformer
,因此只要实现该接口即可,PageTransformer
非常简单,它只有一个方法:
/**
* Apply a property transformation to the given page.
*
* @param page Apply the transformation to this page
* @param position Position of page relative to the current front-and-center
* position of the pager. 0 is front and center. 1 is one full
* page position to the right, and -1 is one page position to the left.
*/
public void transformPage(View view, float position)
transformPage()
方法的关键在于position的理解,从doc注释来看,当前选中的item的position永远是0(这与ViewPager
的OnPageChangeListener
回调方法中的position不同),被选中item的前一个为-1,被选中item的后一个为1。** 其实这里文档的描述并不是完全正确的,前后item position为-1和1的前提是你没有给ViewPager
设置pageMargin
(通过调用viewPager.setPageMargin(int)
方法设置)**。如果你设置了pageMargin
,前后item的position需要分别加上(或减去,前减后加)一个偏移量(偏移量的计算方式为pageMargin / pageWidth
)。
在用户滑动界面的时候,position是动态变化的,下面以左滑为例:
- 选中item position:0->-1 - offset (pageMargin / pageWidth)
- 前一个item position:-1 - offset (pageMargin / pageWidth) -> -2 - offset (pageMargin / pageWidth),再往前就以此类推
- 后一个item position:1 + offset (pageMargin / pageWidth) -> 0,再往后就以此类推
因此我们可以将position的值应用于setAlpha()
, setTranslationX()
, 或者 setScaleY()
等等方法,从而实现自定义的动画效果。
2、示例代码
2.1 布局文件
先看下布局,只有一个RelativeLayout
,内部放置了一个ViewPager
。
<RelativeLayout
android:id="@+id/viewpager_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:clipChildren="false">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="200dp"
android:layout_height="280dp"
android:clipChildren="false"
android:layout_centerInParent="true">
</android.support.v4.view.ViewPager>
</RelativeLayout>
为了ViewPager
可以展示多个Item,这里分别设置其以及其父布局的clipChildren
属性为false。
2.2 滑动技巧
ViewPager
滑动还有一个小技巧,我们都知道默认情况下ViewPager
本身滑动才可以切换页面,所以就算屏幕上显示了多个item,当你滑动未被选中的item时,ViewPager
也是无法切换页面的。如果想扩大滑动区域可以给ViewPager
的父布局设置触摸监听,并将触摸事件交给ViewPager
处理,这样即使滑动触摸位置为未选中item,ViewPager
仍然可以相应滑动了。代码如下:
relativeLayout = (RelativeLayout) view.findViewById(R.id.viewpager_container);
relativeLayout.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return viewPager.onTouchEvent(event);
}
});
2.3 自定义PageTransformer
class MyPageTransform implements ViewPager.PageTransformer {
final float SCALE_MAX = 0.8f;
final float ALPHA_MAX = 0.5f;
@Override
public void transformPage(View page, float position) {
float scale = (position < 0)
? ((1 - SCALE_MAX) * position + 1)
: ((SCALE_MAX - 1) * position + 1);
float alpha = (position < 0)
? ((1 - ALPHA_MAX) * position + 1)
: ((ALPHA_MAX - 1) * position + 1);
//为了滑动过程中,page间距不变,这里做了处理
if(position < 0) {
ViewCompat.setPivotX(page, page.getWidth());
ViewCompat.setPivotY(page, page.getHeight() / 2);
} else {
ViewCompat.setPivotX(page, 0);
ViewCompat.setPivotY(page, page.getHeight() / 2);
}
ViewCompat.setScaleX(page, scale);
ViewCompat.setScaleY(page, scale);
ViewCompat.setAlpha(page, Math.abs(alpha));
}
}
2.3 实现效果
自定义
PageTransformer
实现ViewPager
切换动画的分析到此结束,知道原理后其他炫酷动画效果自然就简单了。