今天興趣來潮,擼了一個動畫特效伸刃,我把他應(yīng)用在登錄的界面,當(dāng)然也可以用在其他地方,先來預(yù)覽一下我的特效吧
使用方法
- 在build.gradle里面配置如下
dependencies {
compile 'com.jzp:rotate3D:1.0.0'
}
- 生成一個Rotate3D對象
Rotate3D anim = new Rotate3D.Builder(this)
.bindParentView(parent_ll)
.bindPositiveView(account_login_ll)
.bindNegativeView(account_phone_ll)
.create();
這里面必須要設(shè)置的參數(shù)是bindParentView惑灵,bindPositiveView,bindNegativeView眼耀,這些分別是父類View英支,正面View,以及旋轉(zhuǎn)后的反面View哮伟,有提供可選參數(shù)
- setDuration 設(shè)置動畫時間
- setDepthZ 設(shè)置Z軸深度
可選參數(shù)未設(shè)置的話就使用默認的
- 啟動動畫
anim.transform();
實現(xiàn)原理
由于android提供的動畫 alpha(淡入淡出)干花,translate(位移),scale(縮放大欣慊啤)池凄,rotate(旋轉(zhuǎn)),這些都是平面上的動畫鬼廓,那想要做3D立體的動畫肿仑,我們就需要從寫animation,3D立體動畫用到android的Camera庫碎税,Camera提供了三種旋轉(zhuǎn)方法:
- rotateX()
- rotateY()
- rotateX()
調(diào)用這三種方法尤慰,傳入旋轉(zhuǎn)角度參數(shù),即可實現(xiàn)視圖沿著坐標軸旋轉(zhuǎn)的功能雷蹂。
實現(xiàn)的核心代碼
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;
float scale = 1; // 像素密度
/**
* 創(chuàng)建一個繞 y 軸旋轉(zhuǎn)的3D動畫效果伟端,旋轉(zhuǎn)過程中具有深度調(diào)節(jié),可以指定旋轉(zhuǎn)中心匪煌。
*
* @param context 上下文,用于獲取像素密度
* @param fromDegrees 起始時角度
* @param toDegrees 結(jié)束時角度
* @param centerX 旋轉(zhuǎn)中心x坐標
* @param centerY 旋轉(zhuǎn)中心y坐標
* @param depthZ 最遠到達的z軸坐標
* @param reverse true 表示由從0到depthZ责蝠,false相反
*/
public Rotate3dAnimation(Context context, float fromDegrees, float toDegrees,
float centerX, float centerY, float depthZ, boolean reverse) {
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();
}
@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();
// 調(diào)節(jié)深度
if (mReverse) {
camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
} else {
camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
}
// 繞y軸旋轉(zhuǎn)
camera.rotateY(degrees);
camera.getMatrix(matrix);
camera.restore();
// 修正失真
float[] mValues = new float[9];
matrix.getValues(mValues); //獲取數(shù)值
mValues[6] = mValues[6] / scale; //數(shù)值修正
mValues[7] = mValues[7] / scale; //數(shù)值修正
matrix.setValues(mValues); //重新賦值
// 調(diào)節(jié)中心點党巾,旋轉(zhuǎn)中心默認是坐標原點,對于圖片來說就是左上角位置霜医。
matrix.preTranslate(-centerX, -centerY); // 使用pre將旋轉(zhuǎn)中心移動到和Camera位置相同
matrix.postTranslate(centerX, centerY); // 使用post將圖片(View)移動到原來的位置
}
}
總結(jié)
代碼中的作用我都有寫注釋昧港,所以在這里就不多解釋了,有的時候支子,我們看一些特效覺得做起來一定很麻煩创肥,其實只要你掌握其實現(xiàn)原理,并不是很難值朋,所以給大家一句忠告叹侄,多讀源碼,對技術(shù)的提升很有幫助昨登。
參考文獻:http://www.reibang.com/p/153d9f31288d 我是根據(jù)這篇博客進行封裝的趾代,謝謝亦楓大神的分享