2013-08-02 22 views
14

從Android 3.0開始,我們有可能使用setRotationX和setRotationY來設置基本的3D視圖轉換爲視圖。如何設置任意變換矩陣到視圖?

在一個特定的情況下,我需要實現一個複雜的轉換,它圍繞一個遙遠的軸心點旋轉,然後在不同的軸心點上進行縮放。這是不可能的,只需使用setScaleX/Y和setRotationX/Y,因爲它們共享相同的支點。

是否有任何簡單的方法來提供所需的矩陣顯示視圖?

現在,我已經發現了兩個可能的解決方法:

  • 建立一個旋轉矩陣,然後用它來映射{0,0}點;將結果點應用到視圖的平移,然後使用視圖的setScaleX/Y設置縮放

  • 對視圖的onDraw進行掃描並在畫布上應用轉換。添加邏輯來反轉地圖觸摸事件。

這兩者都不是很方便,因爲我構建的AdapterView使用可配置的效果顯示其項目;例如,可以將效果切換爲將項目排列成圓形或像「封面流」一樣。

回答

7

我也正在爲此而絞盡腦汁。這是我想出來的(超級哈克)最好的:

MyAnimation animation = new MyAnimation(matrix); 
animation.setDuration(0); 
animation.setFillAfter(true); 
view.setAnimation(animation); 
2

xtravar的答案是偉大的,MyAnimation實現這裏

private class MyAnimation extends Animation { 
    private Matrix matrix; 

    public MyAnimation(Matrix matrix) { 
     this.matrix = matrix; 
    } 

    @Override 
    protected void applyTransformation(float interpolatedTime, Transformation t) { 
     super.applyTransformation(interpolatedTime, t); 
     t.getMatrix().set(matrix); 
    } 
} 
3

以上的動漫作品中的解決方案,但它會導致從效率的角度來看,對於applyTransformation的無限呼叫有點不理想。此外,如果您殺死動畫,則應用的矩陣對視圖而言不是永久的,所以您被迫讓它永遠運行。這裏有一個替代少哈克的方法,在只有setMatrix單一的通話每次invalidate()導致的觀點被稱爲:

在家長看來構造:

setStaticTransformationsEnabled(true); 

然後在身體:

@Override 
    protected boolean getChildStaticTransformation(View child, Transformation t) { 

    // apply transform to child view - child triggers this call by call to `invalidate()` 
    t.getMatrix().set(someMatrix); 
    return true; 
} 

只要你想要更新它的矩陣,只需致電invalidate()即可。

+0

這對我有用,有兩個注意事項。對變換矩陣的每次更新都需要遍歷子視圖來調用每個子視圖的無效 - parent.invalidate()沒有這樣做。此外,我必須禁用基礎Activity上的硬件加速 - 將父級的圖層類型設置爲Software(以代碼/構造函數或XML格式)是不夠的。有可能在視圖層次結構中的其他位置成功禁用硬件加速... – MandisaW

+0

ETA:修改我先前的評論 - 這是一種任意或情況。 *如果*硬件加速被禁用/關閉,那麼parent.invalidate()就可以。 *如果*硬件加速啓用/打開,那麼我發現我需要在更新轉換後調用child.invalidate()。似乎與繪製操作順序有關,如下所述:https://developer.android.com/guide/topics/graphics/hardware-accel.html#model – MandisaW