这次的文章主要是有应用上的需求需要实现翻转效果,然后我在github上找到了一个实现的代码,在此基础上稍微加了一点,这是原文https://github.com/GcsSloop/Rotate3dAnimation 这里面主要是针对像素比较高的手机修复了翻转时的效果不对的问题,然后我扩展了一下针对X轴的翻转,之后发现X轴的翻转也存在翻转失真的问题,所以我运用对矩阵一知半解的知识解决了一下X轴翻转时的失真问题,然后准备对其代码做一个分析,同时也要对矩阵的知识做一点深入了解,现在先放代码
/**
* 3D翻转特效
* @ClassName: Rotate3dAnimation
* @author sloop
* @date 2015年3月10日 上午11:20:10
*/
public class Rotate3dAnimation 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;
ContextThemeWrapper context;
//新增--像素比例(默认值为1)
float scale = 1;
/**
* 创建一个新的实例 Rotate3dAnimation.
* @param fromDegrees 开始角度
* @param toDegrees 结束角度
* @param centerX 中心点x坐标
* @param centerY 中心点y坐标
* @param depthZ 深度
* @param reverse 是否扭曲
*/
public Rotate3dAnimation(ContextThemeWrapper context, float fromDegrees, float toDegrees, float centerX, float centerY, float depthZ, boolean reverse) {
this.context = context;
mFromDegrees = fromDegrees;
mToDegrees = toDegrees;
mCenterX = centerX;
mCenterY = centerY;
mDepthZ = depthZ;
mReverse = reverse;
//获取手机像素比 (即dp与px的比例)
scale = context.getResources().getDisplayMetrics().density;
}
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
mCamera = new Camera();
}
// 生成Transformation
@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) {
camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
} else {
camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
}
// camera.rotateX(degrees);//沿着X轴翻转
camera.rotateY(degrees);//沿着Y轴翻转
// 取得变换后的矩阵
camera.getMatrix(matrix);
camera.restore();
//----------------------------------------------------------------------------
/**
* 修复打脸问题
* 简要介绍:
* 原来的3D翻转会由于屏幕像素密度问题而出现效果相差很大
* 例如在屏幕像素比为1,5的手机上显示效果基本正常,
* 而在像素比3,0的手机上面感觉翻转感觉要超出屏幕边缘,
* 有种迎面打脸的感觉、
*
* 解决方案
* 利用屏幕像素密度对变换矩阵进行校正,
* 保证了在所有清晰度的手机上显示的效果基本相同。
*
*/
float[] mValues = {0,0,0,0,0,0,0,0,0};
matrix.getValues(mValues); //获取数值
mValues[7] = mValues[7]/scale; //X轴翻转时的数值修正
mValues[6] = mValues[6]/scale; //Y轴数值修正
matrix.setValues(mValues); //重新赋值
// Log.e("TAG", "mValues["+0+"]="+mValues[0]+"------------\t"+"mValues["+6+"]="+mValues[6]);
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
}
}
public class MainActivity extends Activity {
ImageView image;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
image = (ImageView) findViewById(R.id.image);
image.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
applyRotation(0, 70);
}
});
}
private void applyRotation(float start, float end) {
// 计算中心点
final float centerX = image.getWidth() / 2.0f;
final float centerY = image.getHeight() / 2.0f;
final Rotate3dAnimation rotation = new Rotate3dAnimation(MainActivity.this, start, end, centerX, centerY, 3.0f, false);
rotation.setDuration(500);
// 动画完成后保持完成的状态
rotation.setFillAfter(true);
rotation.setInterpolator(new AccelerateInterpolator());
rotation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
// if (retuens) {
// retuens = false;
// applyRotation(180, 360);
// }
}
});
image.startAnimation(rotation);
}
}
现在先把关键代码放在这,下班后再开始下一步的分析
今早我瞬间有日了狗了的感觉,今天在测试位移动画的时候,发现了一个属性,然后发现其实实现翻转效果已经有现成的方法了,放出代码
ObjectAnimator goInAnim = new ObjectAnimator();
goInAnim.setFloatValues(0,360f);
goInAnim.setDuration(5000);
goInAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (Float) animation.getAnimatedValue();
view.setRotationY(value);
}
});
有木有日了狗了的感觉?!昨天还去调试矩阵,结果今天发现这个属性就能实现翻转效果!