ViewPager自带了一个setPageTransformer用于设置切换动画(该方法在SDK11以下的版本不起作用)
官方文档:
1.mViewPager.setPageTransformer(true, new DepthPageTransformer());
缩放效果
import android.support.v4.view.ViewPager; import android.view.View; public class DepthPageTransformer implements ViewPager.PageTransformer { private static final float MIN_SCALE = 0.75f; public void transformPage(View view, float position) { int pageWidth = view.getWidth(); if (position < -1) { // [-Infinity,-1) // This page is way off-screen to the left. view.setAlpha(0); } else if (position <= 0) { // [-1,0] // Use the default slide transition when moving to the left page view.setAlpha(1); view.setTranslationX(0); view.setScaleX(1); view.setScaleY(1); } else if (position <= 1) { // (0,1] // Fade the page out. view.setAlpha(1 - position); // Counteract the default slide transition view.setTranslationX(pageWidth * -position); // Scale the page down (between MIN_SCALE and 1) float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position)); view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); } else { // (1,+Infinity] // This page is way off-screen to the right. view.setAlpha(0); } } }
2.mViewPager.setPageTransformer(true, new ZoomOutPageTransformer());
移动加缩放
import android.support.v4.view.ViewPager; import android.view.View; public class ZoomOutPageTransformer implements ViewPager.PageTransformer { private static final float MIN_SCALE = 0.85f; private static final 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) // This page is way off-screen to the left. view.setAlpha(0); } else if (position <= 1) //a页滑动至b页 ; a页从 0.0 -1 ;b页从1 ~ 0.0 { // [-1,1] // Modify the default slide transition to shrink the page as well 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); } // Scale the page down (between MIN_SCALE and 1) view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); // Fade the page relative to its size. view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA)); } else { // (1,+Infinity] // This page is way off-screen to the right. view.setAlpha(0); } } } 自定义:(自定义ViewPage) 1.如何获得当前View和目的View 通过onPageScrolled(int position, float positionOffset, int positionOffsetPixels)ViewPager在添加一个View或者销毁一个View时,是我们自己的PageAdapter中控制的,于是我们可以在ViewPager里面维系一个HashMap<Position,View>,然后滑动的时候,通过get(position)取出,比如上述效果,始终是右边的View变化,要么从小到大,要么从大到小
那么滑倒下一页:左边的View:map.get(position) ,右边的View : map.get(position+1) .
那么滑倒上一页:左边的View : map.get(position) , 右边的View : map.get(position+1) ,
一样的,因为滑到上一页,position为当前页-1
在非第一页与最后一页时,滑动到下一页,position为当前页位置;滑动到上一页:position为当前页-1,
positionOffset 滑动到下一页,[0,1)区间上变化;滑动到上一页:(1,0]区间上变化
positionOffsetPixels这个和positionOffset很像:滑动到下一页,[0,宽度)区间上变化;滑动到上一页:(宽度,0]区间上变化
第一页时:滑动到上一页position=0 ,其他基本为0 ;最后一页滑动到下一页 position为当前页位置,其他两个参数为0
豁然发现,positionOffset很适合作为,渐变,缩放的控制参数;positionOffsetPixels则可以作为平移等的控制参数。
3.原理
通过findViewFromObject(position); findViewFromObject(position + 1);分别获取了左右两边的View,然后添加动画效果;当前这个例子添加了两个动画,一个是从0.5放大到1.0或者1.0缩小到0.5,没错由我们的positionOffset提供梯度的变化~~还有个平移的动画:下一页直接移动到当前屏幕(默认是在右边,可以注释这个效果,怎么运行看看),然后不断的通过positionOffsetPixels抵消原来默认移动时的位移,让用户感觉它就在原地放大缩小~~
- import java.util.LinkedHashMap;
- import android.content.Context;
- import android.support.v4.view.ViewPager;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.View;
- import com.nineoldandroids.view.ViewHelper;
- public class MyJazzyViewPager extends ViewPager
- {
- private float mTrans;
- private float mScale;
- /**
- * 最大的缩小比例
- */
- private static final float SCALE_MAX = 0.5f;
- private static final String TAG = "MyJazzyViewPager";
- /**
- * 保存position与对于的View
- */
- private HashMap<Integer, View> mChildrenViews = new LinkedHashMap<Integer, View>();
- /**
- * 滑动时左边的元素
- */
- private View mLeft;
- /**
- * 滑动时右边的元素
- */
- private View mRight;
- public MyJazzyViewPager(Context context, AttributeSet attrs)
- {
- super(context, attrs);
- }
- @Override
- public void onPageScrolled(int position, float positionOffset,
- int positionOffsetPixels)
- {
- //滑动特别小的距离时,我们认为没有动,可有可无的判断
- float effectOffset = isSmall(positionOffset) ? 0 : positionOffset;
- //获取左边的View
- mLeft = findViewFromObject(position);
- //获取右边的View
- mRight = findViewFromObject(position + 1);
- // 添加切换动画效果
- animateStack(mLeft, mRight, effectOffset, positionOffsetPixels);
- super.onPageScrolled(position, positionOffset, positionOffsetPixels);
- }
- public void setObjectForPosition(View view, int position)
- {
- mChildrenViews.put(position, view);
- }
- /**
- * 通过过位置获得对应的View
- *
- * @param position
- * @return
- */
- public View findViewFromObject(int position)
- {
- return mChildrenViews.get(position);
- }
- private boolean isSmall(float positionOffset)
- {
- return Math.abs(positionOffset) < 0.0001;
- }
- protected void animateStack(View left, View right, float effectOffset,
- int positionOffsetPixels)
- {
- if (right != null)
- {
- /**
- * 缩小比例 如果手指从右到左的滑动(切换到后一个):0.0~1.0,即从一半到最大
- * 如果手指从左到右的滑动(切换到前一个):1.0~0,即从最大到一半
- */
- mScale = (1 - SCALE_MAX) * effectOffset + SCALE_MAX;
- /**
- * x偏移量: 如果手指从右到左的滑动(切换到后一个):0-720 如果手指从左到右的滑动(切换到前一个):720-0
- */
- mTrans = -getWidth() - getPageMargin() + positionOffsetPixels;
- ViewHelper.setScaleX(right, mScale);
- ViewHelper.setScaleY(right, mScale);
- ViewHelper.setTranslationX(right, mTrans);
- }
- if (left != null)
- {
- left.bringToFront();
- }
- }
- }
4.用法
mViewPager.setTransitionEffect(TransitionEffect.Stack);
开源项目: https://github.com/jfeinstein10/JazzyViewPager