Android 3D旋转动画之Camera 和 Matrix

前面两篇博文讲解的都是Android 的2D动画效果,要想做出非常炫酷的3D动画效果怎么办?android 并没有提供3D动画接口给用户,所以我们得自己重写这样一个3D接口动画。

接口如下:

/*
 * @Title: My3dAnimation.java
 * @Description: TODO<请描述此文件是做什么的>
 * @author: xjp
 * @data: 2014年9月15日 上午8:54:10
 * @version: V1.0
 */
package com.xjp.animator;

import android.graphics.Camera;
import android.graphics.Matrix;
import android.view.animation.Animation;
import android.view.animation.Transformation;

/**
 * TODO<请描述这个类是干什么的>
 * 
 * @author xjp
 * @data: 2014年9月15日 上午8:54:10
 * @version: V1.0
 */
public class My3dAnimation extends Animation {

	private final float mFromDegrees;
	private final float mToDegrees;
	private final float mCenterX;
	private final float mCenterY;
	private final float mDepthZ;
	private Camera mCamera;
	private int mDirection;
	private final static int ROTATE_X = 0;//沿着x轴旋转
	private final static int ROTATE_Y = 1;//沿着y轴旋转

	/**
	 * Creates a new 3D rotation on the Y axis. The rotation is defined by its
	 * start angle and its end angle. Both angles are in degrees. The rotation
	 * is performed around a center point on the 2D space, definied by a pair of
	 * X and Y coordinates, called centerX and centerY. When the animation
	 * starts, a translation on the Z axis (depth) is performed. The length of
	 * the translation can be specified, as well as whether the translation
	 * should be reversed in time.
	 * 
	 * @param direction
	 *            the direction of the 3D rotation
	 * @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
	 */
	public My3dAnimation(int direction, float fromDegrees, float toDegrees,
			float centerX, float centerY, float depthZ) {
		mDirection = direction;
		mFromDegrees = fromDegrees;
		mToDegrees = toDegrees;
		mCenterX = centerX;
		mCenterY = centerY;
		mDepthZ = depthZ;
	}

	@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 (centerX!=0){
			if (interpolatedTime < 0.5) {
				camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
			} else {
				camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
			}
		}
		
		switch (mDirection) {
		case ROTATE_X:
			camera.rotateX(degrees);
			break;
		case ROTATE_Y:
			camera.rotateY(degrees);
			break;
		}

		camera.getMatrix(matrix);
		camera.restore();
		matrix.preTranslate(-centerX, -centerY);
		matrix.postTranslate(centerX, centerY);
	}
}

示例代码如下:

package com.xjp.animator;

import com.xjp.animator.R;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.app.Activity;

public class MainActivity extends Activity implements
		android.view.View.OnClickListener {

	private ImageView img1;
	private ImageView img2;
	private ImageView img3;
	private ViewGroup mContainer;
	private final static int ROTATE_X = 0;
	private final static int ROTATE_Y = 1;
	private My3dAnimation my3dAnimation;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		findViews();
	}

	/**
	 * TODO<请描述这个方法是干什么的>
	 * 
	 * @throw
	 * @return void
	 * @param
	 */
	private void findViews() {
		// TODO Auto-generated method stub
		mContainer = (ViewGroup) findViewById(R.id.container);
		mContainer
				.setPersistentDrawingCache(ViewGroup.PERSISTENT_ANIMATION_CACHE);

		img1 = (ImageView) findViewById(R.id.img_left);
		img1.setOnClickListener(this);
		img2 = (ImageView) findViewById(R.id.img_right);
		img2.setOnClickListener(this);

		img3 = (ImageView) findViewById(R.id.img_3);
		img3.setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		float centerX = v.getWidth() / 2.0f;
		float centerY = v.getHeight() / 2.0f;
		if (v.getId() == R.id.img_left) {
			my3dAnimation = new My3dAnimation(ROTATE_X, 0, 180, centerX,
					centerY, 310f);
		}
		if (v.getId() == R.id.img_right) {
			my3dAnimation = new My3dAnimation(ROTATE_Y, 0, 180, centerX,
					centerY, 310f);
		}
		if (v.getId() == R.id.img_3) {
			centerX = 0;
			my3dAnimation = new My3dAnimation(ROTATE_Y, 0, 20, centerX,
					centerY, 310f);
		}
		my3dAnimation.setDuration(1000);
		my3dAnimation.setInterpolator(new LinearInterpolator());
		my3dAnimation.setFillAfter(true);
		v.startAnimation(my3dAnimation);
	}
}

完结。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。