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最后有源码提供下载:
完整Demo源码戳这里:(还有些简单其他的学习valueAnimator,objectAnimator动画的小效果)
http://download.csdn.net/detail/themelove/9425177
先看效果:
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
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories