Android立体旋转动画实现与封装(支持以X、Y、Z三个轴为轴心旋转)
本文主要介绍Android立体旋转动画,或者3D旋转,下图是我自己实现的一个界面
立体旋转分为以下三种:
1. 以X轴为轴心旋转
2. 以Y轴为轴心旋转
3. 以Z轴为轴心旋转--这种等价于android默认自带的旋转动画RotateAnimation
实现立体旋转核心步骤:
1. 继承系统Animation重写applyTransformation方法
通过applyTransformation方法的回调参数 float interpolatedTime, Transformation t 来控制旋转动画
interpolatedTime 用来计算旋转角度而 t 用来控制变换矩阵从而实现图像的旋转
2. android.graphics.Camera控制旋转算法
Camera可以对图像执行一些比较复杂的操作--旋转,绽放,与Matrix一起实现图像的倾斜
核心代码封装:Rotate3dAnimation
package rotateanim.example.com.androidrotateanim; import android.view.animation.Animation; import android.view.animation.Transformation; import android.graphics.Camera; import android.graphics.Matrix; /** * An animation that rotates the view on the X,Y,Z axis between two specified angles. * This animation also adds a translation on the Z axis (depth) to improve the effect. */ public class Rotate3dAnimation extends Animation { public static final Byte ROTATE_X_AXIS = 0x00; public static final Byte ROTATE_Y_AXIS = 0x01; public static final Byte ROTATE_Z_AXIS = 0x02; 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; private Byte mRotateAxis; // 0:X轴 1:Y轴 2:Z轴 /**创建3D旋转动画 * @param fromDegrees the start angle of the 3D rotation * @param toDegrees the end angle of the 3D rotation * @param centerX the X center of the 3D rotation * @param centerY the Y center of the 3D rotation * @param depthZ the Z depth of the 3D rotation * @param rotateAxis the rotate axis of the 3D rotation * @param reverse true if the translation should be reversed, false otherwise */ public Rotate3dAnimation(float fromDegrees, float toDegrees, float centerX, float centerY, float depthZ, Byte rotateAxis, boolean reverse) { mFromDegrees = fromDegrees; mToDegrees = toDegrees; mCenterX = centerX; mCenterY = centerY; mDepthZ = depthZ; mRotateAxis = rotateAxis; mReverse = reverse; } @Override public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); mCamera = new Camera(); } @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) { // z的偏移会越来越大。这就会形成这样一个效果,view从近到远 camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime); } else { // z的偏移会越来越小。这就会形成这样一个效果,我们的View从一个很远的地方向我们移过来,越来越近,最终移到了我们的窗口上面 camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime)); } // 是给我们的View加上旋转效果,在移动的过程中,视图还会以XYZ轴为中心进行旋转。 if (ROTATE_X_AXIS.equals(mRotateAxis)) { camera.rotateX(degrees); } else if (ROTATE_Y_AXIS.equals(mRotateAxis)) { camera.rotateY(degrees); } else { camera.rotateZ(degrees); } // 这个是将我们刚才定义的一系列变换应用到变换矩阵上面,调用完这句之后,我们就可以将camera的位置恢复了,以便下一次再使用。 camera.getMatrix(matrix); // camera位置恢复 camera.restore(); // 下面两句是为了动画是以View中心为旋转点 matrix.preTranslate(-centerX, -centerY); matrix.postTranslate(centerX, centerY); } }
Rotate3dAnimation使用:跟普通动画使用没区别,设置给一个View对象,启动动画就搞定
mRotateImgv就是需要旋转的View对象 // 以X轴为轴心旋转 private void rotateOnXCoordinate() { float centerX = mRotateImgv.getWidth() / 2.0f; float centerY = mRotateImgv.getHeight() / 2.0f; float depthZ = 0f; Rotate3dAnimation rotate3dAnimationX = new Rotate3dAnimation(0, 180, centerX, centerY, depthZ, Rotate3dAnimation.ROTATE_X_AXIS, true); rotate3dAnimationX.setDuration(1000); mRotateImgv.startAnimation(rotate3dAnimationX); } // 以X轴为轴心旋转 private void rotateOnYCoordinate() { float centerX = mRotateImgv.getWidth() / 2.0f; float centerY = mRotateImgv.getHeight() / 2.0f; float centerZ = 0f; Rotate3dAnimation rotate3dAnimationX = new Rotate3dAnimation(0, 180, centerX, centerY, centerZ, Rotate3dAnimation.ROTATE_Y_AXIS, true); rotate3dAnimationX.setDuration(1000); mRotateImgv.startAnimation(rotate3dAnimationX); } // 以Z轴为轴心旋转---等价于普通平面旋转动画 private void rotateAnimHorizon() { float centerX = mRotateImgv.getWidth() / 2.0f; float centerY = mRotateImgv.getHeight() / 2.0f; float centerZ = 0f; Rotate3dAnimation rotate3dAnimationX = new Rotate3dAnimation(180, 0, centerX, centerY, centerZ, Rotate3dAnimation.ROTATE_Z_AXIS, true); rotate3dAnimationX.setDuration(1000); mRotateImgv.startAnimation(rotate3dAnimationX); // 下面是使用android自带的旋转动画 // RotateAnimation rotateAnimation = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); // rotateAnimation.setDuration(1000); // mRotateImgv.startAnimation(rotateAnimation); }