package cn.pedant.SweetAlert; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Camera; import android.graphics.Matrix; import android.util.AttributeSet; import android.util.TypedValue; import android.view.animation.Animation; import android.view.animation.Transformation; public class Rotate3dAnimation extends Animation { private int mPivotXType = ABSOLUTE; private int mPivotYType = ABSOLUTE; private float mPivotXValue = 0.0f; private float mPivotYValue = 0.0f; private float mFromDegrees; private float mToDegrees; private float mPivotX; private float mPivotY; private Camera mCamera; private int mRollType; public static final int ROLL_BY_X = 0; public static final int ROLL_BY_Y = 1; public static final int ROLL_BY_Z = 2; protected static class Description { public int type; public float value; } Description parseValue(TypedValue value) { Description d = new Description(); if (value == null) { d.type = ABSOLUTE; d.value = 0; } else { if (value.type == TypedValue.TYPE_FRACTION) { d.type = (value.data & TypedValue.COMPLEX_UNIT_MASK) == TypedValue.COMPLEX_UNIT_FRACTION_PARENT ? RELATIVE_TO_PARENT : RELATIVE_TO_SELF; d.value = TypedValue.complexToFloat(value.data); return d; } else if (value.type == TypedValue.TYPE_FLOAT) { d.type = ABSOLUTE; d.value = value.getFloat(); return d; } else if (value.type >= TypedValue.TYPE_FIRST_INT && value.type <= TypedValue.TYPE_LAST_INT) { d.type = ABSOLUTE; d.value = value.data; return d; } } d.type = ABSOLUTE; d.value = 0.0f; return d; } public Rotate3dAnimation (Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Rotate3dAnimation); mFromDegrees = a.getFloat(R.styleable.Rotate3dAnimation_fromDeg, 0.0f); mToDegrees = a.getFloat(R.styleable.Rotate3dAnimation_toDeg, 0.0f); mRollType = a.getInt(R.styleable.Rotate3dAnimation_rollType, ROLL_BY_X); Description d = parseValue(a.peekValue(R.styleable.Rotate3dAnimation_pivotX)); mPivotXType = d.type; mPivotXValue = d.value; d = parseValue(a.peekValue(R.styleable.Rotate3dAnimation_pivotY)); mPivotYType = d.type; mPivotYValue = d.value; a.recycle(); initializePivotPoint(); } public Rotate3dAnimation (int rollType, float fromDegrees, float toDegrees) { mRollType = rollType; mFromDegrees = fromDegrees; mToDegrees = toDegrees; mPivotX = 0.0f; mPivotY = 0.0f; } public Rotate3dAnimation (int rollType, float fromDegrees, float toDegrees, float pivotX, float pivotY) { mRollType = rollType; mFromDegrees = fromDegrees; mToDegrees = toDegrees; mPivotXType = ABSOLUTE; mPivotYType = ABSOLUTE; mPivotXValue = pivotX; mPivotYValue = pivotY; initializePivotPoint(); } public Rotate3dAnimation (int rollType, float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) { mRollType = rollType; mFromDegrees = fromDegrees; mToDegrees = toDegrees; mPivotXValue = pivotXValue; mPivotXType = pivotXType; mPivotYValue = pivotYValue; mPivotYType = pivotYType; initializePivotPoint(); } private void initializePivotPoint() { if (mPivotXType == ABSOLUTE) { mPivotX = mPivotXValue; } if (mPivotYType == ABSOLUTE) { mPivotY = mPivotYValue; } } @Override public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); mCamera = new Camera(); mPivotX = resolveSize(mPivotXType, mPivotXValue, width, parentWidth); mPivotY = resolveSize(mPivotYType, mPivotYValue, height, parentHeight); } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { final float fromDegrees = mFromDegrees; float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime); final Matrix matrix = t.getMatrix(); mCamera.save(); switch (mRollType) { case ROLL_BY_X: mCamera.rotateX(degrees); break; case ROLL_BY_Y: mCamera.rotateY(degrees); break; case ROLL_BY_Z: mCamera.rotateZ(degrees); break; } mCamera.getMatrix(matrix); mCamera.restore(); matrix.preTranslate(-mPivotX, -mPivotY); matrix.postTranslate(mPivotX, mPivotY); } }