参考:https://github.com/rubensousa/ViewPagerCards
原理:
-
实现ViewPager.PageTransformer,接管ViewPager的页面转换操作。接口唯一方法transformPage空实现。
-
ViewPager#setPageTransformer()设置自定义的实现类,ViewPager#addOnPageChangeListener,重写onPageScrolled方法。
-
卡片效果CardView#setMaxCardElevation(),且xml中app:cardUseCompatPadding="true"则会把elevation的值为padding间隔。
package com.github.rubensousa.viewpagercards;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.CardView;
import android.util.Log;
import android.view.View;
public class ShadowTransformer implements ViewPager.OnPageChangeListener, ViewPager.PageTransformer {
private ViewPager mViewPager;
private CardAdapter mAdapter;
private float mLastOffset;
private boolean mScalingEnabled;
public ShadowTransformer(ViewPager viewPager, CardAdapter adapter) {
mViewPager = viewPager;
viewPager.addOnPageChangeListener(this);
mAdapter = adapter;
}
public void enableScaling(boolean enable) {
if (mScalingEnabled && !enable) {
// shrink main card
CardView currentCard = mAdapter.getCardViewAt(mViewPager.getCurrentItem());
if (currentCard != null) {
currentCard.animate().scaleY(1);
currentCard.animate().scaleX(1);
}
}else if(!mScalingEnabled && enable){
// grow main card
CardView currentCard = mAdapter.getCardViewAt(mViewPager.getCurrentItem());
if (currentCard != null) {
currentCard.animate().scaleY(1.1f);
currentCard.animate().scaleX(1.1f);
}
}
mScalingEnabled = enable;
}
@Override
public void transformPage(View page, float position) {
}
/**
* 原currentItem缩小比例、新currentItem放大比例
* 1、positionOffset控制CardView的animate
* positionOffset范围:[0,1)
* 右滑时positionOffset从0到1逐渐增大,到达下一个item时,position加1,positionOffset归0
* 左滑时positionOffset从1到0逐渐减小,刚开始滑动时position就减1,positionOffset减小到0
* 2、positionOffset与上一次比较判断左滑右滑
* 3、效果上来看,只有当前item和下一个要展示的item需要动画效果;如右滑时,当前item左侧的item无需动画效果
* @param position
* @param positionOffset
* @param positionOffsetPixels
*/
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
Log.d("Trans","position = " + position + " ,positionOffset = " + positionOffset);
int realCurrentPosition;
int nextPosition;
float baseElevation = mAdapter.getBaseElevation();
float realOffset;
boolean goingLeft = mLastOffset > positionOffset;
// If we're going backwards, onPageScrolled receives the last position
// instead of the current one
if (goingLeft) {
realCurrentPosition = position + 1; //左滑时,position其实是左侧item位置
nextPosition = position;
realOffset = 1 - positionOffset; //左滑时,positionOffset 1 -> 0
} else {
nextPosition = position + 1;
realCurrentPosition = position;
realOffset = positionOffset;
}
// Avoid crash on overscroll
if (nextPosition > mAdapter.getCount() - 1
|| realCurrentPosition > mAdapter.getCount() - 1) {
return;
}
CardView currentCard = mAdapter.getCardViewAt(realCurrentPosition);
// This might be null if a fragment is being used
// and the views weren't created yet
if (currentCard != null) {
if (mScalingEnabled) {
currentCard.setScaleX((float) (1 + 0.1 * (1 - realOffset)));
currentCard.setScaleY((float) (1 + 0.1 * (1 - realOffset)));
}
}
CardView nextCard = mAdapter.getCardViewAt(nextPosition);
// We might be scrolling fast enough so that the next (or previous) card
// was already destroyed or a fragment might not have been created yet
if (nextCard != null) {
if (mScalingEnabled) {
nextCard.setScaleX((float) (1 + 0.1 * (realOffset)));
nextCard.setScaleY((float) (1 + 0.1 * (realOffset)));
}
}
mLastOffset = positionOffset;
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
}
网友评论