转载请标明出处: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