參考:https://github.com/rubensousa/ViewPagerCards
原理:
實現(xiàn)ViewPager.PageTransformer,接管ViewPager的頁面轉(zhuǎn)換操作。接口唯一方法transformPage空實現(xiàn)。
ViewPager#setPageTransformer()設(shè)置自定義的實現(xiàn)類,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逐漸增大,到達(dá)下一個item時,position加1,positionOffset歸0
* 左滑時positionOffset從1到0逐漸減小,剛開始滑動時position就減1,positionOffset減小到0
* 2、positionOffset與上一次比較判斷左滑右滑
* 3、效果上來看,只有當(dāng)前item和下一個要展示的item需要動畫效果;如右滑時,當(dāng)前item左側(cè)的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其實是左側(cè)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) {
}
}