您的位置:首页 > 运维架构

3D旋转动画的自定义FlopView

2016-02-01 23:38 295 查看
前言:很多普通App都有类型3D旋转图片的需求,有些人会问Android中属性动画和valueAnimator,objectAnimator出现以后,都直接提供了RotationX(绕X轴旋转,3D效果),RotationY(绕Y轴旋转,3D效果),RotationZ(绕Z轴旋转:这个其实和View动画的旋转是一样的,平面的感觉,在valueAnimator和objectAnimator中,只是在空间上的一个维度,所以valueAnimator和objectAnimator肯定比View动画强大的多),那为什么还要自定义呢?因为系统提供的只能选择一个view对象,比如,一张图片,一个imageView旋转过后的背面还是这张图片,但是我们的需求往往是翻转过后的背面是另一张图片,所以我们这里介绍的自定义控件其实就是对我们要执行旋转动画的View对象的一个封装,让其旋转到一定角度后显示另一个view视图,不复杂,比较简单。

先看效果:



gridView中的应用



具体实现:原理同网上的rotation3dAnimation的实现基本相同,利用2个view视图的显示与隐藏,这里我们利用的是android中valueAnimator来实现的,利用valueAnimator设置监听方法addUpdateListener来实现的;(如果有不是很明白valueAnimator的同学,请移步大神的bolghttp://my.csdn.net/harvic880925,这篇bolg也是了看大神的bolg后改进以前项目中类似效果的)提供了设置动画时间setDuration,设置资源文件为翻转的正反面setForeAndBackImage,以及设置复杂布局为翻转为正反面的setForeAndBackVeiw的方法,以及开启动画的方法和旋转方向setAnimatorType(即围绕哪个方向旋转):

flopView自定义控件核心代码如下:(代码中我都加了注释)至于Demo中的怎么调用,怎么造GridView中假数据,以及测试Activity中的代码就不贴出来了有需要的同学blog最后有源码提供下载:

public class FlopView extends FrameLayout {

private Context mContext;
public static final int ROTATION_X = 0;//绕X轴旋转
public static final int ROTATION_Y = 1;//绕Y轴旋转
public static final int ROTATION_Z = 2;//绕Z轴旋转
public float[] mAnimArgsOne = new float[]{0, 90, 180};//动画的动态参数
public float[] mAnimArgsTwo = new float[]{180, 270, 360};//动画的动态参数
public int mDuration = 1000;//动画时长:默认1000毫秒
public int mRunningCount;//已经成功执行动画的次数

private int mAnimatorType = ROTATION_Y;//默认为竖直方法旋转

private ValueAnimator mAnimator;
private ValueAnimator mAnimatorOne;
private ValueAnimator mAnimatorTwo;

public FlopView(Context context) {
super(context);
mContext = context;
init();
}

public FlopView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
init();
}

public FlopView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
init();
}

private void init() {
initAnimation();//初始化动画

//给自身设置点击事件
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startAnimation();//执行动画
}
});

}

/**
* 设置旋转动画的类型 分X轴,Y轴,Z轴
*/
public void setAnimatorType(int rotationType) {
if (mAnimator != null) {
mAnimator.cancel();
}
if (mAnimArgsOne != null) {
mAnimatorOne.cancel();
}
if (mAnimatorTwo != null) {
mAnimatorTwo.cancel();
}
mRunningCount = 0;
mAnimatorType = rotationType;
}

/**
* 设置动画时长
*
* @param duration 时长
*/
public void setmDuration(int duration) {
mDuration = duration;
}

/*    */

/**
* 设置参数
*
* @param args
*//*
public void setArgs(float... args){
if (args!=null){
for (int i = 0; i <args.length ; i++) {
mAnimArgsOne[i]=args[i];
}
}
}*/

//根据当前动画的状态判断是否开启动画
private void startAnimation() {

if (mRunningCount % 2 == 0) {
mAnimator = mAnimatorOne;
} else {
mAnimator = mAnimatorTwo;
}
if (mAnimator == null)
return;
if (mAnimatorOne.isRunning() || mAnimatorTwo.isRunning()) {
Toast.makeText(mContext, "还没结束,不理你0.0", Toast.LENGTH_SHORT).show();
return;
}
/*       mIsRunning = mAnimator.isRunning();
if (mIsRunning) {
Toast.makeText(mContext,"还没结束,不理你0.0",Toast.LENGTH_SHORT).show();
return;
}*/
mRunningCount++;
mAnimator.start();
}

/**
* 设置动画的前景色和背景色
*
* @param foreSrcId 前景
* @param backSrcId 背景
*/
public void setForeAndBackImage(int foreSrcId, int backSrcId) {
this.removeAllViews();
if (mAnimator != null) {
mAnimator.cancel();
}
if (mAnimArgsOne != null) {
mAnimatorOne.cancel();
}
if (mAnimatorTwo != null) {
mAnimatorTwo.cancel();
}
mRunningCount = 0;

ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
ImageView foreImage = new ImageView(mContext);
ImageView backImage = new ImageView(mContext);

foreImage.setImageResource(foreSrcId);
backImage.setImageResource(backSrcId);

addView(backImage, 0, params);
addView(foreImage, 1, params);
}

/**
* 设置动画的前景 和 背景要显示的View
*
* @param foreView 前景View
* @param backView 背景View
*/
public void setForeAndBackView(View foreView, View backView) {
this.removeAllViews();
if (foreView.getParent() != null) {
((LinearLayout) foreView.getParent()).removeView(foreView);
}
if (backView.getParent() != null) {
((LinearLayout) backView.getParent()).removeView(backView);
}

if (mAnimator != null) {
mAnimator.cancel();
}
if (mAnimArgsOne != null) {
mAnimatorOne.cancel();
}
if (mAnimatorTwo != null) {
mAnimatorTwo.cancel();
}
mRunningCount = 0;

ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
addView(backView, 0, params);
addView(foreView, 1, params);
}

/**
* 初始化动画
*/
private void initAnimation() {
if (mAnimatorOne == null) {
mAnimatorOne = ValueAnimator.ofFloat(mAnimArgsOne);
mAnimatorOne.setDuration(mDuration);
mAnimatorOne.setInterpolator(new LinearInterpolator());//匀速的插值器
mAnimatorOne.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
if (getChildCount() > 0 && getChildCount() == 2) {
//                        如果有2个孩子,让其执行动画
if (mAnimatorType == ROTATION_X) {
getChildAt(0).setRotationX(value);
getChildAt(1).setRotationX(value);
} else if (mAnimatorType == ROTATION_Y) {
getChildAt(0).setRotationY(value);
getChildAt(1).setRotationY(value);
}
if (value >= 0 && value <= 90) {
if (mRunningCount % 2 == 0) {
getChildAt(1).setVisibility(View.INVISIBLE);
getChildAt(0).setVisibility(View.VISIBLE);
} else {
getChildAt(1).setVisibility(View.VISIBLE);
getChildAt(0).setVisibility(View.INVISIBLE);
}
} else if (value > 90 && value <= 180) {
if (mRunningCount % 2 == 0) {
getChildAt(1).setVisibility(View.VISIBLE);
getChildAt(0).setVisibility(View.INVISIBLE);
} else {
getChildAt(1).setVisibility(View.INVISIBLE);
getChildAt(0).setVisibility(View.VISIBLE);
}
}
}
}
});
}

if (mAnimatorTwo == null) {
mAnimatorTwo = ValueAnimator.ofFloat(mAnimArgsTwo);
mAnimatorTwo.setDuration(mDuration);
mAnimatorTwo.setInterpolator(new LinearInterpolator());//匀速的插值器
mAnimatorTwo.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
if (getChildCount() > 0 && getChildCount() == 2) {
//如果有2个孩子,让其执行动画
if (mAnimatorType == ROTATION_X) {
getChildAt(0).setRotationX(value);
getChildAt(1).setRotationX(value);
} else if (mAnimatorType == ROTATION_Y) {
getChildAt(0).setRotationY(value);
getChildAt(1).setRotationY(value);
}
if (value >= 180 && value <= 270) {
if (mRunningCount % 2 == 0) {
getChildAt(1).setVisibility(View.INVISIBLE);
getChildAt(0).setVisibility(View.VISIBLE);
} else {
getChildAt(1).setVisibility(View.VISIBLE);
getChildAt(0).setVisibility(View.INVISIBLE);
}
} else if (value > 270 && value <= 360) {
if (mRunningCount % 2 == 0) {
getChildAt(1).setVisibility(View.VISIBLE);
getChildAt(0).setVisibility(View.INVISIBLE);
} else {
getChildAt(1).setVisibility(View.INVISIBLE);
getChildAt(0).setVisibility(View.VISIBLE);
}
}
}
}
});
}

}

}

完整Demo源码戳这里:(还有些简单其他的学习valueAnimator,objectAnimator动画的小效果)

http://download.csdn.net/detail/themelove/9425177
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息