@TryLoveCatch
2018-10-19T14:58:06.000000Z
字数 3873
阅读 2046
android
自定义View
实例
ViewPager
实现一个引导页,当ViewPager滑动一段时间之后,背景大图跟着滑动。这样我们组合前面的两篇文章:
超大图片处理
ViewPager背景渐变
我们在ViewPager背景渐变这个基础上来开发,只需要增加大图的滑动就可以了。
参考ViewPager背景渐变关于OnPageChangeListener
的介绍,想法就是:在onPageSelected()
调用的时候,我们执行大图动画,这样就可以实现上面说的需求了。
@Override
public void onPageSelected(int position) {
Log.e("MainActivity", "onPageSelected====position: " + position);
handleDots(position);
mIsPositionChanged = true;
handleBcIconAnim(mCurrentPosition);
}
private void handleBcIconAnim(int pPosition){
if (mScreenWidth <= 0) {
return;
}
ValueAnimator tAnimator;
if (pPosition > mLastPosition) {
tAnimator = ValueAnimator.ofFloat(0f, 1f);
} else {
tAnimator = ValueAnimator.ofFloat(0f, -1f);
}
tAnimator.setDuration(650);
tAnimator.setInterpolator(new DecelerateInterpolator());
tAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float tFloat = (float) animation.getAnimatedValue();
float tMoveX = tFloat * mScreenWidth/2;
mLargeImageView.move(Math.round(tMoveX - mLastMove), 0);
mLastMove = tMoveX;
}
});
tAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
mLastMove = 0;
}
@Override
public void onAnimationEnd(Animator animation) {
mLastMove = 0;
}
});
tAnimator.start();
mLastPosition = pPosition;
}
动画也很简单,就是每次最多移动屏幕宽度的二分之一,然后根据mLastPosition
和pPosition
来判断是左滑还是右滑,决定动画的取值,然后调用
mLargeImageView.move()
即可了。效果如下:
跟咱们需求的基本上一直,但是看效果图,如果快速滑动的时候,后面的大图动画会一卡一卡的,这个肯定是因为动画没有执行完,所以我就想,如果动画正在执行,我就不让ViewPager响应滑动事件。
所以我增加一个布尔值,判断动画是否在执行,然后mViewPager.setOnTouchListener()
,返回这个布尔值即可,如下:
mViewPager.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.e("MainActivity", "setOnTouchListener====");
return mIsAnim;
}
});
效果如下:
好了,解决了快速滑动的问题。但是。。。。当滑动的瞬间,我们朝相反的方向滑动,就会停在两个pager中间的位置。其实这个问题,仔细想想也对,因为mIsAnim
为true,所以我们拦截了ViewPager
的事件,就造成了这个问题。
怎么解决呢?我想的是,我在根布局拦截事件,动画执行的过程中,根本不让事件下发到ViewPager
,应该就能解决这个问题了。代码如下:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.e("MainActivity", "dispatchTouchEvent====");
if(mIsAnim){
return true;
}
return super.dispatchTouchEvent(ev);
}
我重写了Activity
的dispatchTouchEvent()
方法,当动画过程中,拦截,否则走原有逻辑。
这样基本上没问题了,算是一个圆满的结局吧。
上面提到了,我们每次最多移动屏幕的一半,但是这个就有问题,比如我们的大图宽度是2000px,屏幕宽度是1080px,然后有5张page,我每次移动540,这样显示最后一张page的时候,大图不会有动画了,因为已经到头了。
所以需要动态算一下,每次可以移动的最大值,算法也很简单,如下:
mMoveWidth = (mLargeImageView.getImageWidth() - getScreenWidth(this)) / (mArrViews.size() - 1);
图片的宽度-屏幕的宽度,得到剩下的宽度,然后其他几个page平分即可。
本来下载了这里,但是写的比较多,所以专门另起了一篇文章,链接如下:
ViewPage动画PageTransformer分析
直接上代码,如下:
private class MyTransformer implements ViewPager.PageTransformer {
@Override
public void transformPage(View page, float position) {
if (position < -1) { // [-Infinity,-1)
Log.e("MainActivity", "============" + position);
} else if (position <= 1) { // [-1,1]
float scrollXOffset = page.getWidth() * 1.5f;
ViewGroup tViewGroup = (ViewGroup) page;
View tView;
for (int i = 0; i < tViewGroup.getChildCount(); i++) {
tView = tViewGroup.getChildAt(i);
if (tView == null || tView instanceof ImageView) {
continue;
}
tView.setTranslationX(scrollXOffset * position);
// scrollXOffset *= 0.5;
}
} else { // (1,+Infinity]
Log.e("MainActivity", "============" + position);
}
}
}
这里需要注意,我在之前的文章里面也说过
setTranslationX(0)
会恢复TranslationX的值
所以我们利用这个特性,确保在动画结束的时候,setTranslationX()
的参数传入的为0
,这样布局就还原了。
横屏的时候,大图没有刷新,还是显示为竖屏的宽度,这个就需要我们自己刷新一次了,代码如下:
Activity监听onConfigurationChanged()
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mMoveWidth = (mLargeImageView.getImageWidth() - getScreenWidth(this)) / (mArrViews.size() - 1);
if (mLargeImageView != null) {
mLargeImageView.onConfigurationChanged(mCurrentPosition, mMoveWidth);
}
}
public void onConfigurationChanged(int pPosition, int pMoveWidth) {
mIsFirstMeasure = true;
mPosition = pPosition;
mMoveWidth = pMoveWidth;
}
因为有可能,我是在第二页才横屏的,所以需要传position
参数。
实现知乎 Android 客户端启动页视差滚动效果
ViewPager 从入门到带你撸个启动页之实战PageTransformer切换动画特效(四)
Android ViewPager切换之PageTransformer接口中transformPage方法position参数使用详解
用PageTranformer实现更炫酷的动画