网上有很多Win8动态磁贴特效的代码,但是都是使用基于继承ImageView的自定义类,这种实现方法有一个短板就是该类要实现Metro特效必须是以图片为背景的,而且scaleType必须只能指定为matrix。不然特效就出不来。
自己参考了网上的代码很久,自己琢磨出来了使用动画来实现Metro特效,通过继承自Animation来重写里面的protected void applyTransformation(float interpolatedTime, Transformation t)、public boolean getTransformation(long currentTime, Transformation outTransformation)和public void initialize(int width, int height, int parentWidth, int parentHeight) 方法实现的,废话不多说,上代码:
自定义动画类:
<pre name="code" class="java">package com.hwlong.Utils;
import android.graphics.Camera;
import android.graphics.Matrix;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.Transformation;
/**
* 动态磁贴动画
*
* @author HeJie
*
*/
public class MetroAnimation extends Animation {
private int touchX; //触控X坐标
private int touchY; //触控Y坐标
private int mHeight; //View的高度
private int mWidth; //View的宽度
private int count;
private View view; //动画对应的View
private boolean XbigY = false;
private boolean isScale = false; //true使用放缩特效,false则使用反转特效
private boolean mPaused = false;
private boolean isPause = true;
private long mElapsedAtPause = 0;
private float RotateX = 0;
private float RotateY = 0;
private float minK = 0.012f; //放缩函数的斜率
private Camera camera;
public MetroAnimation() {
super();
camera = new Camera();
}
/**
* 设置点击的位置、viewID等信息
* @param touchX
* @param touchY
* @param ViewID
*/
public void setTouchPoint(int touchX, int touchY, View view) {
this.touchX = touchX;
this.touchY = touchY;
this.view = view;
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
if (isScale) {
if (!mPaused) {
float s = 0;
if (count < 10) {
//根据count的值 计算放缩率s的值
s = (1f - count * minK);
BeginScale(t.getMatrix(), s);
} else if (count < 20) {
//放缩特效执行一半时,自动暂停
if (count == 10 && isPause) {
Pause();
}
s = 1f + (count - 19) * minK;
BeginScale(t.getMatrix(), s);
} else {
view.clearAnimation();
}
count++;
} else {
//暂停时缩小矩阵至最小状态
BeginScale(t.getMatrix(), (1f - 10 * minK));
}
} else {
if (!mPaused) {
if (count < 10) {
//count为旋转的角度
BeginRotate(t.getMatrix(), (XbigY ? count : 0), (XbigY ? 0
: count));
} else if (count <= 20) {
//旋转特效执行一半时,自动暂停
if (count == 10 && isPause) {
Pause();
}
//(20 - count)为旋转的角度值
BeginRotate(t.getMatrix(), (XbigY ? 20 - count : 0),
(XbigY ? 0 : 20 - count));
} else {
view.clearAnimation();
}
count += 2;
} else {
//暂停时旋转矩阵至最大状态
BeginRotate(t.getMatrix(), (XbigY ? 10 : 0), (XbigY ? 0 : 10));
}
}
}
@Override
public boolean getTransformation(long currentTime,
Transformation outTransformation) {
//设置暂停后第一次调用该方法,记录暂停时用过的时间
if (mPaused && mElapsedAtPause == 0) {
mElapsedAtPause = currentTime - getStartTime();
}
if (mPaused)
//设置开始时间,不然动画会随暂停的时间流逝而停止
setStartTime(currentTime - mElapsedAtPause);
return super.getTransformation(currentTime, outTransformation);
}
/**
* 暂停动画
*/
public void Pause() {
mElapsedAtPause = 0;
mPaused = true;
}
/**
* 恢复动画
*/
public void Resume() {
mPaused = false;
isPause = false;
}
@Override
public void initialize(int width, int height, int parentWidth,
int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
mWidth = width;
mHeight = height;
count = 0;
isPause = true;
Rot