转载请标明原地址:http://blog.csdn.net/gaolei1201/article/details/50428553
ViewPager 我们比较常用,但是它的切换只有水平滚动着一种方式。最求个性化的现代社会,我么怎么把它打造地个性化些呢?没有你做不到的只有你想不到的,呵呵。
切换动画有两种实现方式:
1.ViewPager自带了一个setPageTransformer用于设置切换动画,本篇先不讲这种方法,有关详情可参考:http://blog.csdn.net/lmj623565791/article/details/40411921 。
2.自定义动画 ,github上有开源项目地址:https://github.com/jfeinstein10/JazzyViewPager 。这种方法需要注意的是,利用View的Animation。所以ViewPager中的内容只能是View,不能是Fragment等非View控件。这篇文章主要是在开源项目的基础上制作几种比较实用的切换动画。
第2种方法实现的原理:
ViewPager也需要监听用户的手势,所以肯定提供了某个方法。于是纵观ViewPager的方法,发现了一个叫做 onPageScrolled(int position, float positionOffset, int positionOffsetPixels)的方法。没错就是这个方法:在页面滚动时调用~
下面仔细研究下这几个参数:
在非第一页与最后一页时,滑动到下一页,position为当前页位置;滑动到上一页:position为当前页-1
positionOffset 滑动到下一页,[0,1)区间上变化;滑动到上一页:(1,0]区间上变化,
positionOffsetPixels这个和positionOffset很像:滑动到下一页,[0,宽度)区间上变化;滑动到上一页:(宽度,0]区间上变化,
第一页时:滑动到上一页position=0 ,其他基本为0 ;最后一页滑动到下一页 position为当前页位置,其他两个参数为0,
豁然发现,我们需要的步骤的第二步解决了,positionOffset很适合作为,渐变,缩放的控制参数;positionOffsetPixels则可以作为平移等的控制参数。
第一种切换动画 "左侧覆盖" 效果:
自定义ViewPager,主要代码:
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";
private HashMap mChildrenViews = new LinkedHashMap();
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) {
// Log.e(TAG, "position=" +
// position+", positionOffset = "+positionOffset+" ,positionOffsetPixels = "
// + positionOffsetPixels+" , currentPos = " + getCurrentItem());
float effectOffset = isSmall(positionOffset) ? 0 : positionOffset;
mLeft = findViewFromObject(position);
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);
}
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,即从最大到一半
*/
mTrans = -getWidth() - getPageMargin() + positionOffsetPixels;
// 利用nineoldandroid.jar控制右侧滑动动画
ViewHelper.setTranslationX(right, mTrans);
}
if (left != null) {
left.bringToFront();
}
}
}
自定义ViewPager代码如下:
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";
private HashMap mChildrenViews = new LinkedHashMap();
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) {
// Log.e(TAG, "position=" +
// position+", positionOffset = "+positionOffset+" ,positionOffsetPixels = "
// + positionOffsetPixels+" , currentPos = " + getCurrentItem());
float effectOffset = isSmall(positionOffset) ? 0 : positionOffset;
mLeft = findViewFromObject(position);
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);
}
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) {
Log.d("gaolei", "effectOffset----------------/" + effectOffset);
Log.d("gaolei", "positionOffsetPixels----------------/"
+ positionOffsetPixels);
if (right != null) {
/**
* 缩小比例 如果手指从右到左的滑动(切换到后一个):0.0~1.0,即从一半到最大
* 如果手指从左到右的滑动(切换到前一个):1.0~0,即从最大到一半 //
*/
right.bringToFront();
}
if (left != null) {
mTrans = positionOffsetPixels;
// 利用nineoldandroid.jar控制右侧滑动动画
ViewHelper.setTranslationX(left, mTrans);
}
}
}
第三种切换动画“左右都滑动”效果:
自定义ViewPager主要代码:
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 mChildrenViews = new LinkedHashMap();
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) {
// Log.e(TAG, "position=" +
// position+", positionOffset = "+positionOffset+" ,positionOffsetPixels = "
// + positionOffsetPixels+" , currentPos = " + getCurrentItem());
// 滑动特别小的距离时,我们认为没有动,可有可无的判断
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) {
Log.d("gaolei", "effectOffset----------------/" + effectOffset);
Log.d("gaolei", "positionOffsetPixels----------------/"
+ positionOffsetPixels);
if (right != null) {
/**
* 缩小比例 如果手指从右到左的滑动(切换到后一个):0.0~1.0,即从一半到最大
* 如果手指从左到右的滑动(切换到前一个):1.0~0,即从最大到一半 /** x偏移量:
*/
right.bringToFront();
}
if (left != null) {
mTrans = positionOffsetPixels;
// 利用nineoldandroid.jar控制左侧滑动动画,修改200可以尝试改变移动距离
ViewHelper.setTranslationX(left, positionOffsetPixels - 200
* effectOffset);
}
}
}