前言:在做App的Splash页面时有一个漂亮的ViewPager切换动画,不仅能让人耳目一新,而且在开发中面对PM的需求也能做到游刃有余。
先看效果图
目录
- 自定义ViewPagerTransform方法介绍
- 自定义ViewPagerTransform
1:自定义ViewPagerTransform方法介绍
直接上码
private void initViewPager1(){
vierPage1.setAdapter(new PagerAdapter() {
@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(tvLists.get(position));
return tvLists.get(position);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(tvLists.get(position));
}
@Override
public int getCount() {
return tvLists.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
});
vierPage1.setPageTransformer(true,new DepthPageTransformer());
}
private void setData() {
int[] colors = new int[]{ContextCompat.getColor(this,R.color.green),
ContextCompat.getColor(this,R.color.red),
ContextCompat.getColor(this,R.color.mediumvioletred)};
TextView textView = null;
for (int i = 0; i < colors.length; i++) {
textView = new TextView(this);
textView.setBackgroundColor(colors[i]);
textView.setText(i+"");
textView.setGravity(Gravity.CENTER);
tvLists.add(textView);
}
}
这里我给给ViewPager设置3个TextView,分别是0,1,2(为什么是TextView呢,这里后面有用到),分别给了不同的背景色,关键在于
vierPage1.setPageTransformer(true,new DepthPageTransformer());
DepthPageTransformer
public class DepthPageTransformer implements ViewPager.PageTransformer {
private static final String TAG = "DepthPageTransformer";
private static final float MIN_SCALE = 0.75f;
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
/**
* position取值特点:
* 假设页面从0~1,则:
* 第一个页面position变化为[0,-1] 当前的View
* 第二个页面position变化为[1,0] 进入的View
*
* @param page
* @param position
*/
@Override
public void transformPage(View view, float position) {
Log.d(TAG,((TextView)view).getText() + "___" + position);
int pageWidth = view.getWidth();
if (position < -1) { // [-Infinity,-1) 不可见的View
view.setAlpha(0);
} else if (position <= 0) { // [-1,0] 当前的View
view.setAlpha(1);
view.setTranslationX(0);
view.setScaleX(1);
view.setScaleY(1);
} else if (position <= 1) { // (0,1] 进入的View
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
view.setAlpha(0);
}
}
}
要使用自定义切换效果必须实现ViewPager.PageTransformer
它的transformerPage 方法虽然有注释,但是不是很好理解,这时候TextView用处就上场了,来看看Log打印出来的东西
页面进入的时候:
05-24 01:46:21.456 1645-1645/norton.animademo D/DepthPageTransformer: 0___0.0
05-24 01:46:21.456 1645-1645/norton.animademo D/DepthPageTransformer: 1___1.0
由 0 ->1
05-24 01:46:25.327 1645-1645/norton.animademo D/DepthPageTransformer: 0___-0.052083332
05-24 01:46:25.327 1645-1645/norton.animademo D/DepthPageTransformer: 1___0.9479167
05-24 01:46:25.345 1645-1645/norton.animademo D/DepthPageTransformer: 0___-0.24722221
05-24 01:46:25.345 1645-1645/norton.animademo D/DepthPageTransformer: 1___0.75277776
05-24 01:46:25.366 1645-1645/norton.animademo D/DepthPageTransformer: 0___-0.52847224
05-24 01:46:25.366 1645-1645/norton.animademo D/DepthPageTransformer: 1___0.47152779
05-24 01:46:25.380 1645-1645/norton.animademo D/DepthPageTransformer: 0___-0.77708334
05-24 01:46:25.380 1645-1645/norton.animademo D/DepthPageTransformer: 1___0.22291666
05-24 01:46:25.394 1645-1645/norton.animademo D/DepthPageTransformer: 0___-0.90833336
05-24 01:46:25.394 1645-1645/norton.animademo D/DepthPageTransformer: 1___0.09166667
05-24 01:46:25.411 1645-1645/norton.animademo D/DepthPageTransformer: 0___-0.9763889
05-24 01:46:25.411 1645-1645/norton.animademo D/DepthPageTransformer: 1___0.023611112
05-24 01:46:25.428 1645-1645/norton.animademo D/DepthPageTransformer: 0___-0.99722224
05-24 01:46:25.428 1645-1645/norton.animademo D/DepthPageTransformer: 1___0.0027777778
05-24 01:46:25.444 1645-1645/norton.animademo D/DepthPageTransformer: 0___-1.0
05-24 01:46:25.444 1645-1645/norton.animademo D/DepthPageTransformer: 1___0.0
由1->2
05-24 01:49:49.110 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.09791667
05-24 01:49:49.110 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.90208334
05-24 01:49:49.110 1645-1645/norton.animademo D/DepthPageTransformer: 0___-1.0979167
05-24 01:49:49.127 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.37013888
05-24 01:49:49.127 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.6298611
05-24 01:49:49.127 1645-1645/norton.animademo D/DepthPageTransformer: 0___-1.3701389
05-24 01:49:49.143 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.58958334
05-24 01:49:49.143 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.41041666
05-24 01:49:49.143 1645-1645/norton.animademo D/DepthPageTransformer: 0___-1.5895833
05-24 01:49:49.160 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.84930557
05-24 01:49:49.160 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.15069444
05-24 01:49:49.160 1645-1645/norton.animademo D/DepthPageTransformer: 0___-1.8493055
05-24 01:49:49.180 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.9611111
05-24 01:49:49.180 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.03888889
05-24 01:49:49.180 1645-1645/norton.animademo D/DepthPageTransformer: 0___-1.9611111
05-24 01:49:49.196 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.99375
05-24 01:49:49.196 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.00625
05-24 01:49:49.196 1645-1645/norton.animademo D/DepthPageTransformer: 0___-1.99375
05-24 01:49:49.212 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.99930555
05-24 01:49:49.212 1645-1645/norton.animademo D/DepthPageTransformer: 2___6.9444446E-4
05-24 01:49:49.212 1645-1645/norton.animademo D/DepthPageTransformer: 0___-1.9993056
05-24 01:49:49.226 1645-1645/norton.animademo D/DepthPageTransformer: 1___-1.0
05-24 01:49:49.226 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.0
05-24 01:49:49.229 1645-1645/norton.animademo D/DepthPageTransformer: 0___-2.0
由2->1
05-24 01:50:20.677 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.9444444
05-24 01:50:20.677 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.055555556
05-24 01:50:20.694 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.68680555
05-24 01:50:20.694 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.31319445
05-24 01:50:20.710 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.4173611
05-24 01:50:20.710 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.58263886
05-24 01:50:20.720 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.33402777
05-24 01:50:20.720 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.66597223
05-24 01:50:20.727 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.23055555
05-24 01:50:20.727 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.76944447
05-24 01:50:20.743 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.06736111
05-24 01:50:20.743 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.9326389
05-24 01:50:20.760 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.014583333
05-24 01:50:20.760 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.98541665
05-24 01:50:20.777 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.0013888889
05-24 01:50:20.777 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.9986111
05-24 01:50:20.794 1645-1645/norton.animademo D/DepthPageTransformer: 1___0.0
05-24 01:50:20.795 1645-1645/norton.animademo D/DepthPageTransformer: 2___1.0
日志出来这个东西就很好解释了
可以看见,transformPage这个方法当中的View的值进入,退出的View 来回依次出现的;
前面的数字就是显示的对应的TextView(这时知道TextView的用处了吧);
对切换而言是有2个对象的,一个是进入的,一个是退出的。
退出的View 的position 是一个 [0,-1] 的值;
进入的View 的position 是一个 [1,0] 的值;
搞懂View和position的关系,现在无论是自定义动画或者自定义View,都很好处理了。
2. 自定义ViewPagerTransform
下面来看看一个ViewPagerTransforms的开源项目
https://github.com/ToxicBakery/ViewPagerTransforms当中的一些炫酷效果
public class CudeOutTransformer implements ViewPager.PageTransformer {
@Override
public void transformPage(View page, float position) {
page.setPivotX(position < 0f ? page.getWidth() : 0f);
page.setPivotY(page.getHeight() * 0.5f);
page.setRotationY(90f * position);
page.setAlpha(position <= -1f || position >= 1f ? 0f : 1f); // 看不见的view
}
}
公式很简单就不多解释了,这里主要是用了一些三元运算符,
轴转动和旋转动画组合起来效果还不错。
public class ZoomInTransformer implements ViewPager.PageTransformer{
@Override
public void transformPage(View view, float position) {
final float width = view.getWidth();
view.setRotationX(0);
view.setRotationY(0);
view.setRotation(0);
view.setScaleX(1);
view.setScaleY(1);
view.setPivotX(0);
view.setPivotY(0);
view.setTranslationY(0);
view.setTranslationX(-width * position);
final float scale = position < 0 ? position + 1f : Math.abs(1f - position);
view.setScaleX(scale);
view.setScaleY(scale);
view.setPivotX(view.getWidth() * 0.5f);
view.setPivotY(view.getHeight() * 0.5f);
view.setAlpha(position < -1f || position > 1f ? 0f : 1f - (scale - 1f)); //不可见View
}
}
这个代码看着挺多的,其实很简单,主要是一个把View移动到中心位置,然后进入的View放大,退出的View缩小。
总结:其实自定义Viewpager的Transform搞清楚
退出的View 的position 是一个 [0,-1] 的值;
进入的View 的position 是一个 [1,0] 的值;
这一点,就很好处理了,动画都是有过度值的,由position确定View,再给View设置一个动画效果,难点在于~ 数学要好!数学要好!