Android 卡片翻转动画效果

转载请标明出处:http://blog.csdn.net/android_mnbvcxz/article/details/78570594 


Android 卡片翻转动画效果


前言

前端时间开发一款应用APP,里面展示的内容需要用到卡片元素,卡片的正面显示主要信息,卡片的背面显示详细信息,单击卡片实现翻转动画的效果。
在这里我给出了两个卡片翻转动画效果的样式,废话不多说,让我们一起看看效果吧:
翻转动画一

翻转动画二



一、卡片翻转动画效果一详解

1.1 界面布局

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/choose_product_item_ly"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:layout_gravity="center"
    android:foreground="?attr/selectableItemBackground"
    app:cardBackgroundColor="@android:color/transparent"
    app:cardCornerRadius="@dimen/radius"
    app:cardElevation="4dp"
    app:cardMaxElevation="4dp"
    app:cardPreventCornerOverlap="true"
    app:cardUseCompatPadding="true">

    <include layout="@layout/ly_choose_product_item_back" /><!--反面布局-->

    <include layout="@layout/ly_choose_product_item_front" /><!--正面布局-->

</android.support.v7.widget.CardView>

:在CardView控件里面include了两个正面和反面两个布局,用于分别显示各自的内容(这里面的代码就不贴了)

1.2 自定义3D旋转动画类(继承Animation)

/**
 * 3D旋转动画
 */
public class Rotate3dAnimation extends Animation {
    // 开始角度
    private final float mFromDegrees;
    // 结束角度
    private final float mToDegrees;
    // 中心点
    private final float mCenterX;
    private final float mCenterY;
    private final float mDepthZ;
    // 是否需要扭曲
    private final boolean mReverse;
    // 摄像头
    private Camera mCamera;

    public Rotate3dAnimation(float fromDegrees, float toDegrees, float centerX,
                             float centerY, float depthZ, boolean reverse) {
        mFromDegrees = fromDegrees;
        mToDegrees = toDegrees;
        mCenterX = centerX;
        mCenterY = centerY;
        mDepthZ = depthZ;
        mReverse = reverse;
    }

    @Override
    public void initialize(int width, int height, int parentWidth,
                           int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
        mCamera = new Camera();
    }

    // 生成Transformation
    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        final float fromDegrees = mFromDegrees;
        // 生成中间角度
        float degrees = fromDegrees
                + ((mToDegrees - fromDegrees) * interpolatedTime);

        final float centerX = mCenterX;
        final float centerY = mCenterY;
        final Camera camera = mCamera;

        final Matrix matrix = t.getMatrix();

        camera.save();
        if (mReverse) {
            camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
        } else {
            camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
        }
        camera.rotateY(degrees);
        // 取得变换后的矩阵
        camera.getMatrix(matrix);
        camera.restore();

        matrix.preTranslate(-centerX, -centerY);
        matrix.postTranslate(centerX, centerY);
    }
}

1.3 设置动画监听

    /**
     * 动画执行动作监听
     */
    private final class DisplayNextView implements Animation.AnimationListener {

        public void onAnimationStart(Animation animation) {
        }

        // 动画结束
        public void onAnimationEnd(Animation animation) {

           item_ly.post(new Runnable() {
                @Override
                public void run() {
                    if (item_front_ly.getVisibility() == View.VISIBLE) {
                        applyRotation(view, 90, 0, false);
                    } else {
                        applyRotation(view, -90, 0, false);
                    }
                }
            });

            if (item_front_ly.getVisibility() == View.VISIBLE) {
                item_front_ly.setVisibility(View.GONE);
                item_back_ly.setVisibility(View.VISIBLE);
                
            } else {
                item_front_ly.setVisibility(View.VISIBLE);
                item_back_ly.setVisibility(View.GONE);
              
            }
        }

        public void onAnimationRepeat(Animation animation) {
        }
    }
:这里动画监听的主要功能是判断:如果之前显示的是正面,则在动画结束后隐藏正面,显示反面;反之,隐藏反面,显示正面

1.4 设置旋转动画

   /**
     * 设置旋转动(画动画效果1)
     * @param view
     * @param start
     * @param end
     * @param reverse
     */
    private void applyRotation(View view, float start, float end, boolean reverse) {
        // 计算中心点
        float centerX = view.getWidth() / 2.0f;
        float centerY = view.getHeight() / 2.0f;
        Rotate3dAnimation rotation = new Rotate3dAnimation(start, end,
                centerX, centerY, 300.0f, reverse);
        rotation.setDuration(300);
        rotation.setFillAfter(true);
        rotation.setInterpolator(new AccelerateInterpolator());
        if (reverse)
            rotation.setAnimationListener(new DisplayNextView()); // 设置监听
        view.startAnimation(rotation);
    }


二、卡片翻转动画效果二详解

2.1 界面布局

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/item_ly"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:layout_gravity="center"
    android:background="@android:color/transparent">

    <include layout="@layout/ly_item_back" /><!--反面布局-->

    <include layout="@layout/ly_item_front" /><!--正面布局-->

</FrameLayout>

2.2 设置动画

    // 设置动画(动画效果1)
    private void setAnimators(final View view) {
        mRightOutSet = (AnimatorSet) AnimatorInflater.loadAnimator(mContext, R.animator.card_flip_anim_out);
        mLeftInSet = (AnimatorSet) AnimatorInflater.loadAnimator(mContext, R.animator.card_filp_anim_in);
        // 设置点击事件
        mRightOutSet.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
                view.setClickable(false);
            }
        });
        mLeftInSet.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                view.setClickable(true);
            }
        });
    }
初始化右出(RightOut)左入(LeftIn)动画, 使用动画集合AnimatorSet。当右出动画开始时, 点击事件无效, 当左入动画结束时, 点击事件恢复.
2.2.1 右出动画(在动画资源文件夹animator中创建动画文件card_flip_anim_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <!--旋转-->
    <objectAnimator
        android:duration="3000"<!--总共旋转时间,单位ms-->
        android:propertyName="rotationY"
        android:valueFrom="0"
        android:valueTo="180"/>

    <!--消失-->
    <objectAnimator
        android:duration="0"
        android:propertyName="alpha"
        android:startOffset="1500"<!--背面布局出现时间(也是正面布局消失时间,正好是总共旋转时间的一半),单位ms-->
        android:valueFrom="1.0"
        android:valueTo="0.0"/>
</set>
:右出 动画会旋转180°, 当旋转一半时, 正面卡片消失

2.2.2 左入动画(在动画资源文件夹animator中创建动画文件card_flip_anim_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">

    <!--消失-->
    <objectAnimator
        android:duration="0"
        android:propertyName="alpha"
        android:valueFrom="1.0"
        android:valueTo="0.0"/>

    <!--旋转-->
    <objectAnimator
        android:duration="3000"
        android:propertyName="rotationY"
        android:valueFrom="-180"
        android:valueTo="0"/>

    <!--出现-->
    <objectAnimator
        android:duration="0"
        android:propertyName="alpha"
        android:startOffset="1500"
        android:valueFrom="0.0"
        android:valueTo="1.0"/>
</set>
:左入动画背面布局 在开始时是隐藏, 逆向旋转, 当旋转一半时, 显示卡片。

2.3 镜头视角

    /**
     * 改变视角距离, 贴近屏幕(动画效果2)
     */
    private void setCameraDistance(View front_ly, View back_ly) {
        int distance = 16000;
        float scale = mContext.getResources().getDisplayMetrics().density * distance;
        front_ly.setCameraDistance(scale);
        back_ly.setCameraDistance(scale);
    }
改变视角, 涉及到旋转卡片的Y轴, 即rotationY, 需要修改视角距离。 如果不修改, 则会超出屏幕高度, 影响视觉体验.

3.4 旋转控制

    /**
     * 翻转动画(动画效果1)
     *
     * @param v
     */
    private void flipCard(View v) {

        // 正面朝上
        if (isShowBack()) {
            setShowBack(false);

            mRightOutSet.setTarget(item_front_ly);
            mLeftInSet.setTarget(item_back_ly);
            mRightOutSet.start();
            mLeftInSet.start();
        } else { // 背面朝上
            setShowBack(true);

            mRightOutSet.setTarget(item_back_ly);
            mLeftInSet.setTarget(item_front_ly);
            mRightOutSet.start();
            mLeftInSet.start();
        }
    }



源码我还没有从项目中剥离出来,要是公司项目一起上传的话,感觉会被砍,所以我就不上传了,要是有问题的话可以相互交流交流。



参考:
http://blog.csdn.net/easyer2012/article/details/50483930



  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值