Android自定义动画--卡牌翻牌动画

Android系统中自带了四种动画,但是都只是平面上的并不能实现我们很常见的翻牌动画,所以今天我们就要通过自定义动画来实现翻牌动画.
要实现翻牌动画,我们需要了解三个类,一个是matrix类,一个是camera类,一个是animation类.

1.matrix类是一个3x3的矩阵,用于控制图像和view的平移,旋转,放缩及斜割,官方封装了针对这些的操作给我们,我们只需要采用其中的matrix.setTranslate();matrix.setRotate();matrix.setScale();方法就可以完成一系列复杂的变换,如果想细致了解matrix的话可以参考http://www.360doc.com/content/11/1215/11/7635_172396706.shtml.下面举一个matrix实现图像变换的简单例子:

public class MyView extends View {

	private Bitmap mBitmap;

	private Matrix mMatrix = new Matrix();

	public MyView(Context context) {

		super(context);

		initialize();

	}

	private void initialize() {		

		mBitmap = ((BitmapDrawable)getResources().getDrawable(R.drawable.show)).getBitmap();		

		float cosValue = (float) Math.cos(-Math.PI/6);

		float sinValue = (float) Math.sin(-Math.PI/6);

		mMatrix.setValues(

				new float[]{

						cosValue, -sinValue, 100,

						sinValue, cosValue, 100,

						0, 0, 2});

	}

	@Override protected void onDraw(Canvas canvas) {

//		super.onDraw(canvas);  //当然,如果界面上还有其他元素需要绘制,只需要将这句话写上就行了。

		canvas.drawBitmap(mBitmap, mMatrix, null);

	}

}
2.camera类,通过使用camera类可以对图片或view进行三维空间的变换,提供了以下常用方法:
  1)getMatrix(Matrix matrix),将camera所做的变换应用到制定matrix中.
  2)rotateX(float deg):将目标组件沿X轴旋转
  3)rotateY(float deg):将目标组件沿Y轴旋转
  4)rotateZ(float deg):将目标组件沿Z轴旋转
  5)translate(float x,float y,float z):把目标组件在三维空间里进行位移变换
  6)applyToCanvas(Canvas canvas):把camera所做的变换应用到canvas中.
3.继承animation,继承animation时关键是要重写该抽象基类的applyTransformation(float interpolatedTime,Transformation t)方法,该方法中两个重要参数说明如下:
  1)interpolatedTime:代表动画的时间进行比.不管动画实际持续时间如何,当动画播放的时候,该参数总是从0到1变化的.
  2)Transformation :该参数代表了补间动画在不同时刻对图形或组件的变形程度.该对象里封装了一个Matrix对象,对他所包装的Matrix对象进行位移,倾斜,旋转等变换时,Transformation将会控制对应的图片或视图进行相应的变换.
接下来,我们看一下我们实现自定义动画的代码:
public class CardInvertAnimation extends Animation{
	//动画的中心点
	private float centerX,centerY;
	//动画的持续时间
	private int duration;
	private Camera camera = new Camera();
	
	public CardInvertAnimation(float centerX, float centerY, int duration) {
		super();
		this.centerX = centerX;
		this.centerY = centerY;
		this.duration = duration;
	}
	@Override
	public void initialize(int width, int height, int parentWidth,
			int parentHeight) {
		// TODO Auto-generated method stub
		super.initialize(width, height, parentWidth, parentHeight);
		//设置动画的持续时间
		setDuration(duration);
		//设置动画结束后效果保留
		setFillAfter(true);
		//设置动画差值器为线性
		setInterpolator(new LinearInterpolator());
		
	}
	/* 该方法的interpolatedTime代表动画时间因子,不论duration时间为多少,它的取值范围都为0-1
	 * @interpolatedTime 总是从0-1
	 * @t 包含了view的矩阵,我们可以改变他的矩阵,进行动画.
	 */
	@Override
	protected void applyTransformation(float interpolatedTime, Transformation t) {
		// TODO Auto-generated method stub
		super.applyTransformation(interpolatedTime, t);
		camera.save();
		//根据interpolatedTime来控制x,y,z上的偏移
//		camera.rotateY(180*interpolatedTime);;
		//获取Transformation中的matrix,并将对应变换应用到matrix上
		Matrix matrix = t.getMatrix();
		camera.getMatrix(matrix);
		
		matrix.preTranslate(-centerX, -centerY);
		matrix.postTranslate(centerX, centerY);
		camera.restore();
	}
}
这里我们要说明一下matrix.preTranslate(-centerX, -centerY);matrix.postTranslate(centerX, centerY);这两个方法的作用,我们知道我们view的坐标系是从(0,0)点开始的,也就是说,如果我们不将matrix的中心点提前移动(0,0)点,我们的翻牌动画会绕着view的左侧进行旋转,所以我们要使用这两个方法来进行matrix中心点的变化,pretranslate是指在rotate之前进行平移操作,postTranslate是在rotatle之后进行平移操作.这样就保证了我们得到的效果是沿着中心点的Y轴进行180度旋转的动画.
下面我们看一下如何使用这个 自定义动画,理想的状态下我们只需要找个view给他setAnimation就好了,但是我们要获取view的中心点,这里会出现一个问题,在oncreate方法中我们获取onMeasureHeight和onMeasureWidth得到值为0,原因是在oncreate方法中,我们的view并没有测量和加载完成,所以我们需要在view加载完成后第一时间得到通知,方便我们获取height和width,经过查阅,我们发现在view加载完成后会调用一个叫onWindowFocusChanged(Boolean hasFocus)的方法,所以我们可以override找个方法,在里面进行height和width的获取,代码如下:
public class MainActivity extends Activity {
	ImageView ig;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		ig = (ImageView) findViewById(R.id.ig);

	}

	/* view加载完成后首先调用的方法
	 * 
	 */
	@Override
	public void onWindowFocusChanged(boolean hasFocus) {
		// TODO Auto-generated method stub
		super.onWindowFocusChanged(hasFocus);
		CardInvertAnimation a = new CardInvertAnimation(ig.getWidth() / 2,
				ig.getHeight() / 2, 5000);
		ig.setAnimation(a);

	}
}



你可能感兴趣的:(安卓基础,android,自定义动画,翻牌动画)