android动画之从源码角度分析动画原理(二)
2015-08-05 10:22
597 查看
1.最重要的类,Animation类,一个抽象类,是所有动画的基类,它定义了Animation的公共属性和方法,属性中最重要的是:AnimationListener和Transformation,动画监听器,监听动画的开始,执行过程,结束,可以实现一些自己的逻辑, Transformation是每一帧动画中包含的信息(平移,旋转,绽放,透明度)方法中最重要的是:
第一个方法由系统调用,根据动画当前时间计算出此时的Transformation信息,不必重写此方法,第二个方法是我们必须重写的, 根据系统由第一个方法计算出的Transformation进行实际的动画实现。
2.由上面的Animation类,可以知道最重要的属性和最重要的方法,两者中都有一个叫Transformation的类,可见此类也是很重要的,到Tranfrormation类中可以看到中最重要的属性就是alphat和Matrix, alpha是真正存放动画的透明度信息的,而Matrix则是存放(平移,旋转,绽放)信息的。由此可见这两个才是真正存放一帧动画的的所有信息的载体。
最重要的方法是getMatrix().得到当前帧动画中的存在矩阵中的所有动画信息。
3.由第二点可知,除了透明度信息外,动画的帧信息又是存放在Matrix类中的,所以我们也要看懂Matrix是如何工作的。到了Matrix类中,我们可以看到,此类中提供了一系列的setXXX,preXXX,postXXX方法,即三个系列的对Rotate,Scale,Translate的设置。查阅了网上一些文章,大概明白了三个方法的区别。preXXX方法是对原始矩阵进行右乘,即M*A(以后的M代表原始矩阵),postXXX代表对原始矩阵进行左乘,即 B*M, setXXX代表对原始矩阵数据先清空,再进行右乘。左乘与右乘的区别就是,矩阵进行乘积时会先进行右乘,右乘都执行完后再执行左乘,对应到动画的效果中就是,先叠加右乘矩阵的效果数据,再叠加左乘矩阵的效果数据。可知:左乘与右乘后的效果是完全不同的。具体的矩阵运算说见此文,说的非常好。android Matrix理论与应用。矩阵的都由android系统帮我们处理,程序员要做的只是将偏移量传入到对应的方法中即可。
4.android系统为我们提供的动画都是最基本的,二维的,所以所有的3D动画都要我们自己来实现,而android为我们提供了graphic.camera包下的Camera类,这个类就是实现3D效果的类,我对这个类的理解就是:android系统为我们的程序提供了一双眼睛。就是这个Camera,我们的人眼是可以从XYZ三个轴去观察,那这个Camera也是可以的,通过对Camera类在不同轴上的移动,也是可以达到动画效果的,从Camera类的代码中可以看出它的几个方法:public native void translate(float x, float y, float z)和public native void rotate(float x, float y, float z) ,public void getMatrix(Matrix matrix).这三个方法,第一个是在xyz三个轴上对Camera进行移动,Camera向左移,则可以达到向右的平移动画效果。其它平移效果同理。第二个方法则是在XYZ轴上的旋转,通过在这三个轴上进行旋转,可以达到立体的动画效果,第三个方法则是将在Camera上的操作全部叠加到Matric对象中。
将以上四个类的作用全部搞懂后,我们就基本明白了android的动画原理, 通过继承基类:Aniomation并重写applyTransformation,并将一些效果利用Matrix,Camera实现,就是动画。
下面,我们通过Camera来实现一般的旋转动画和3D旋转动画,以及利用Camear实现我们常用的缩放动画。
1)利用Camera实现平移动画..
2)利用Camera实现旋转动画.
3D动画的实现:
public boolean getTransformation(long currentTime, Transformation outTransformation);和 protected void applyTransformation(float interpolatedTime, Transformation t)。
第一个方法由系统调用,根据动画当前时间计算出此时的Transformation信息,不必重写此方法,第二个方法是我们必须重写的, 根据系统由第一个方法计算出的Transformation进行实际的动画实现。
2.由上面的Animation类,可以知道最重要的属性和最重要的方法,两者中都有一个叫Transformation的类,可见此类也是很重要的,到Tranfrormation类中可以看到中最重要的属性就是alphat和Matrix, alpha是真正存放动画的透明度信息的,而Matrix则是存放(平移,旋转,绽放)信息的。由此可见这两个才是真正存放一帧动画的的所有信息的载体。
最重要的方法是getMatrix().得到当前帧动画中的存在矩阵中的所有动画信息。
3.由第二点可知,除了透明度信息外,动画的帧信息又是存放在Matrix类中的,所以我们也要看懂Matrix是如何工作的。到了Matrix类中,我们可以看到,此类中提供了一系列的setXXX,preXXX,postXXX方法,即三个系列的对Rotate,Scale,Translate的设置。查阅了网上一些文章,大概明白了三个方法的区别。preXXX方法是对原始矩阵进行右乘,即M*A(以后的M代表原始矩阵),postXXX代表对原始矩阵进行左乘,即 B*M, setXXX代表对原始矩阵数据先清空,再进行右乘。左乘与右乘的区别就是,矩阵进行乘积时会先进行右乘,右乘都执行完后再执行左乘,对应到动画的效果中就是,先叠加右乘矩阵的效果数据,再叠加左乘矩阵的效果数据。可知:左乘与右乘后的效果是完全不同的。具体的矩阵运算说见此文,说的非常好。android Matrix理论与应用。矩阵的都由android系统帮我们处理,程序员要做的只是将偏移量传入到对应的方法中即可。
4.android系统为我们提供的动画都是最基本的,二维的,所以所有的3D动画都要我们自己来实现,而android为我们提供了graphic.camera包下的Camera类,这个类就是实现3D效果的类,我对这个类的理解就是:android系统为我们的程序提供了一双眼睛。就是这个Camera,我们的人眼是可以从XYZ三个轴去观察,那这个Camera也是可以的,通过对Camera类在不同轴上的移动,也是可以达到动画效果的,从Camera类的代码中可以看出它的几个方法:public native void translate(float x, float y, float z)和public native void rotate(float x, float y, float z) ,public void getMatrix(Matrix matrix).这三个方法,第一个是在xyz三个轴上对Camera进行移动,Camera向左移,则可以达到向右的平移动画效果。其它平移效果同理。第二个方法则是在XYZ轴上的旋转,通过在这三个轴上进行旋转,可以达到立体的动画效果,第三个方法则是将在Camera上的操作全部叠加到Matric对象中。
将以上四个类的作用全部搞懂后,我们就基本明白了android的动画原理, 通过继承基类:Aniomation并重写applyTransformation,并将一些效果利用Matrix,Camera实现,就是动画。
下面,我们通过Camera来实现一般的旋转动画和3D旋转动画,以及利用Camear实现我们常用的缩放动画。
1)利用Camera实现平移动画..
package com.example.animationdemo; import android.graphics.Camera; import android.graphics.Matrix; import android.view.animation.Animation; import android.view.animation.Transformation; public class CameraTranslateAnimation extends Animation { private float mFromXValue = 0.0f; private float mToXValue = 0.0f; private float mFromYValue = 0.0f; private float mToYValue = 0.0f; private float centerX, centerY; private Camera camera; public CameraTranslateAnimation(float fromXValue, float toXValue, float fromYValue, float toYValue, float centerX, float centerY) { this.mFromXValue = fromXValue; this.mToXValue = toXValue; this.mFromYValue = fromYValue; this.mToYValue = toYValue; this.centerX = centerX; this.centerY = centerY; } @Override public void initialize(int width, int height, int parentWidth, int parentHeight) { // TODO Auto-generated method stub super.initialize(width, height, parentWidth, parentHeight); camera = new Camera(); } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { float dx = (mFromXValue + (mToXValue - mFromXValue) * interpolatedTime); float dy = (mFromYValue + (mToYValue - mFromYValue) * interpolatedTime); Matrix m = t.getMatrix(); camera.save(); camera.translate(dx, dy, 0); // 给要移动的坐标传值 camera.getMatrix(m); camera.restore(); m.preTranslate(-centerX, -centerY); m.postTranslate(centerX, centerY); // 回到中心点 } }
2)利用Camera实现旋转动画.
package com.example.animationdemo; import android.graphics.Camera; import android.graphics.Matrix; import android.view.animation.Animation; import android.view.animation.Transformat 4000 ion; public class CameraRotateAnimation 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 CameraRotateAnimation(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) { // TODO Auto-generated method stub super.initialize(width, height, parentWidth, parentHeight); mCamera = new Camera(); } /** * 注意 applyTransformation函数也是一个不停循环调用的过程.和Adapter中的getView类似 * 绘制动画时,总是根据Transformation中的位置,缩放,平移等信息去绘制每一帧, 从而达到动画的效果 */ @Override protected void applyTransformation(float interpolatedTime, Transformation t) { // TODO Auto-generated method stub 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(); // 得到Transformation中的所有动画信息矩阵(都存放在矩阵中) camera.save(); if (mReverse) { camera.translate(0.0f, 0.0f, -mDepthZ * interpolatedTime); // 在不同轴上的平移效果,通过移动Camear实现 } else { camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime)); } camera.rotateY(degrees); // 将角度变化用在Y轴上, 用在Z轴上的旋转是,则是普通的旋转 camera.getMatrix(matrix); // 必须将此矩阵信息叠加到动画的矩阵中,否则在Camera上的设置都不起作用 camera.restore(); matrix.preTranslate(-centerX, -centerY); //回到中心点 matrix.postTranslate(centerX, centerY); } }
3D动画的实现:
import android.graphics.Camera; import android.view.animation.Animation; import android.view.animation.Transformation; /** * <p>3D旋转动画。<br> * 这个动画可以将对象沿x、y或者z轴进行旋转。</p> * <p>用法参考: * <pre> * View vAnim = <已经初始化好了的View对象>; * Rotate3dAnimation r3 = new Rotate3dAnimation( * 0, 720, // 旋转两周。 * 240, 120, // 以(240, 120)为中心进行旋转。 * true, 1000, // 采用由近及远的景深,景深距离1000。 * Rotate3dAnimation.AXIS_TYPE.Y); // 沿Y轴进行旋转。 * vAnim.setAnimation(r3); // 绑定动画对象。 * r3.setDuration(5000); // 设置动画持续时间为5秒。 * vAnim.startAnimation(r3); // 开始播放动画。 * </pre> * </p> */ public class Rotate3dAnimation extends Animation { /** * <p>旋转过程中需要使用的摄像机对象。</p> */ private Camera camera = null; // 这个摄像机对象调用的是图形包里面的那个类,而不是硬件camera。 /** * <p>旋转的起始角度。</p> */ private float fromDegrees ; /** * <p>旋转的终止角度。</p> */ private float toDegrees ; /** * <p>旋转的类型的终止角度。</p> */ private int mPivotType; /** * <p>旋转的中心点x坐标。</p> */ private float mPivotXValue ; /** * <p>旋转的中心点y坐标。</p> */ private float mPivotYValue ; /** * <p>旋转的中心点x坐标。</p> */ private float centerX ; /** * <p>旋转的中心点y坐标。</p> */ private float centerY ; /** * <p>景深效果是否应该采用由近及远。</p> */ private boolean isReverse ; /** * <p>景深设置。</p> */ private float depthZ ; /** * <p>主轴种类。</p> */ public static enum AXIS_TYPE{ /** * <p>水平旋转。</p> */ X, /** * <p>垂直旋转。</p> */ Y, /** * <p>沿Z轴旋转。</p> */ Z}; /** * <p>旋转时候的主轴。</p> */ private AXIS_TYPE axis; /** * <p>3D旋转动画的构造方法。</p> * @param fromDegrees 开始的角度。 * @param toDegrees 结束的角度。 * @param pivotXValue 旋转的中心处x坐标。 * @param pivotYValue 旋转的中心处y坐标。 * @param reverse 景深效果是否采用由近及远,当depthZ被设置为0时无效。 * @param depthZ 景深。 * @param pivotType 选转类型。可采用值: * Amimation.ABSOLUTE,Amimation.RELATIVE_TO_SELF,Amimation.RELATIVE_TO_PARENT * @param axis 旋转轴。可取的值有:AXIS_TYPE.X、AXIS_TYPE.Y、AXIS_TYPE.Z * @see AXIS_TYPE#X * @see AXIS_TYPE#Y * @see AXIS_TYPE#Z */ public Rotate3dAnimation(float fromDegrees, float toDegrees, float pivotXValue, float pivotYValue, boolean reverse, float depthZ, int pivotType,AXIS_TYPE axis){ this.fromDegrees = fromDegrees; this.toDegrees = toDegrees; this.mPivotXValue = pivotXValue; this.mPivotYValue = pivotYValue; this.mPivotType = pivotType; this.isReverse = reverse; this.depthZ = depthZ; this.axis = axis; this.camera = new Camera(); } /** * <p>3D旋转动画的构造方法。</p> * @param fromDegrees 开始的角度。 * @param toDegrees 结束的角度。 * @param pivotXValue 旋转的中心处x坐标。 * @param pivotYValue 旋转的中心处y坐标。 * isReverse : false。 * depthZ :0。 * pivotType :RELATIVE_TO_SELF * @param axis 旋转轴。可取的值有:AXIS_TYPE.X、AXIS_TYPE.Y、AXIS_TYPE.Z * @see AXIS_TYPE#X * @see AXIS_TYPE#Y * @see AXIS_TYPE#Z */ public Rotate3dAnimation(float fromDegrees, float toDegrees, float pivotXValue, float pivotYValue, AXIS_TYPE axis){ this.fromDegrees = fromDegrees; this.toDegrees = toDegrees; this.mPivotXValue = pivotXValue; this.mPivotYValue = pivotYValue; this.mPivotType = RELATIVE_TO_SELF; this.isReverse = false; this.depthZ = 0; this.axis = axis; this.camera = new Camera(); } /** * <p>3D旋转动画的构造方法。</p> * @param fromDegrees 开始的角度。 * @param toDegrees 结束的角度。 * pivotXValue:0。 * pivotYValue :0。 * isReverse :false。 * depthZ :0。 * pivotType :RELATIVE_TO_SELF * @param axis 旋转轴。可取的值有:AXIS_TYPE.X、AXIS_TYPE.Y、AXIS_TYPE.Z * @see AXIS_TYPE#X * @see AXIS_TYPE#Y * @see AXIS_TYPE#Z */ public Rotate3dAnimation(float fromDegrees, float toDegrees, AXIS_TYPE axis){ this.fromDegrees = fromDegrees; this.toDegrees = toDegrees; this.mPivotXValue =0; this.mPivotYValue = 0; this.mPivotType = RELATIVE_TO_SELF; this.isReverse = false; this.depthZ = 0; this.axis = axis; this.camera = new Camera(); } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { // super.applyTransformation(interpolatedTime, t); float degrees = fromDegrees + ((toDegrees - fromDegrees) * interpolatedTime); camera.save(); if (isReverse) { camera.translate(0.0f, 0.0f, depthZ * interpolatedTime); } else { camera.translate(0.0f, 0.0f, depthZ * (1.0f - interpolatedTime)); } if (AXIS_TYPE.Y.equals(axis)){ camera.rotateY(degrees); } else if(AXIS_TYPE.X.equals(axis)){ camera.rotateX(degrees); } else if(AXIS_TYPE.Z.equals(axis)){ camera.rotateZ(degrees); } b133 camera.getMatrix(t.getMatrix()); camera.restore(); t.getMatrix().preTranslate(-centerX, -centerY); t.getMatrix().postTranslate(centerX, centerY); } @Override public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); centerX = resolveSize(mPivotType, mPivotXValue, width, parentWidth); centerY = resolveSize(mPivotType, mPivotYValue, height, parentHeight); } }
相关文章推荐
- 使用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