ViewPager实现卡片式效果

参考:https://github.com/rubensousa/ViewPagerCards
原理:

  1. 实现ViewPager.PageTransformer,接管ViewPager的页面转换操作。接口唯一方法transformPage空实现。

  2. ViewPager#setPageTransformer()设置自定义的实现类,ViewPager#addOnPageChangeListener,重写onPageScrolled方法。

  3. 卡片效果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) {

    }
}

你可能感兴趣的:(ViewPager实现卡片式效果)