首先,android裏是沒有3D翻轉的動畫效果的,可是呢,android有提供一個Camera的類,能夠利用這個類來實現。java
先看代碼,Rotate3d是繼承了Animation的一個動畫類,多餘的代碼我就不給出了,只看applyTransformation方法內是怎麼實現的。android
public class Rotate3d extends Animation {app
...ide
@Overridepost
protected void applyTransformation(float interpolatedTime, Transformation t) {動畫
final float fromDegrees = mFromDegrees;spa
// 生成中間角度3d
float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);rest
final float centerX = mCenterX;orm
final float centerY = mCenterY;
final Camera camera = mCamera;
final Matrix matrix = t.getMatrix();
camera.save();
// 左右翻轉
camera.rotateY(degrees);
// 取得變換後的矩陣
camera.getMatrix(matrix);
camera.restore();
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
}
...
}
接下來解析下原理。
一、先獲取視圖的Matrix:
final Matrix matrix = t.getMatrix();
二、利用camera改變matrix的參數:
camera.rotateY(degrees);//翻轉必定的角度
camera.getMatrix(matrix);//改變matrix
PS:注意這裏是用getMatrix的方法來改變,順便普及一下小知識,java的方法傳入的參數若是是對象的話,是能夠在方法內改變對象的屬性值的;不過若是傳入的是一個int、float、String之類的基礎類型,則不會改變。舉例:
假若有個方法 set(int i){ i++; } 而後用了 int i=3; set(i); 這時打印出的 i 仍是3。
可是 假若有個方法 set(C c){ c.i++; } 而後用了 c = new C(); c.i=3; set(c); 這時打印出 c 對象的 i 就是4了。
三、繼續,通常上面的步驟已經能夠見到3D翻轉效果了,可是很難看,由於這種翻轉是沒有中心點的,接下來就是將翻轉後的視圖弄到一個位置上去(其實這麼說也不太對)。
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
這個的話其實我也研究了很久最後沒研究出個因此然來,反正記住這樣寫就能夠設置以某個座標爲中心進行翻轉了。
---------------------------我叫分割線--------------------------
最近搞的一個項目須要用到有3D翻轉效果的gallery,卡了我很久。
上面給出的代碼是製做一個3D翻轉的動畫效果,可是若是要在gallery中用到這種動畫效果的話天然不行。主要是翻轉角度的計算問題。
animation動畫類中能夠根據動畫發生的時間點來計算角度,而gallery就不行,由於gallery是隨手勢滑動發生動畫的,時間不固定,還能夠左右來回滑動。
不過只要解決了角度的問題,3D翻轉效果天然不是問題。先看代碼。
@Override
protected boolean getChildStaticTransformation(View child, Transformation t) {
final float centerX = App.width / 2;
final float centerY = App.height / 2;
final Camera camera = mCamera;
camera.save();
float rotate = -child.getLeft() * 90 / 480;
camera.rotateY(rotate);
camera.getMatrix(t.getMatrix());
camera.restore();
t.getMatrix().preTranslate(-centerX, -centerY);
t.getMatrix().postTranslate(centerX, centerY);
return true;
}
這是重寫gallery的一個方法,具體的角度計算,其實就是根據當前視圖View child與左屏幕的距離來計算(也能夠當成是x座標)。
好~效果出來了!仍是挺有成就感的~~ >v<