如何将任意变换矩阵设置为View?

时间:2013-08-02 15:15:50

标签: android android-view transformation

从Android 3.0开始,我们可以使用setRotationX和setRotationY为视图设置基本的3D转换。

在特定情况下,我需要实现一个复杂的变换,即围绕一个远点,然后在不同的枢轴点上缩放。简单地使用setScaleX / Y和setRotationX / Y是不可能的,因为它们共享相同的轴心点。

是否有任何简单的方法可以为视图提供所需的矩阵以供显示?

目前,我找到了两种可能的解决方法:

  • 设置旋转矩阵,然后用它来映射{0,0}点;将结果点应用于View的翻译,然后使用View的setScaleX / Y设置缩放

  • 破解View的onDraw并在画布上应用转换。添加逻辑以反转地图触摸事件。

两者都不是很方便,因为我正在构建一个使用可配置效果显示其项目的AdapterView;例如,可以切换效果以使项目以圆圈形式排列或像“封面流程”一样。

3 个答案:

答案 0 :(得分:9)

我也是在为此辩护。这是我提出的最好的(超级hacky):

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

答案 1 :(得分:5)

上面的动画解决方案有效,但它会导致对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()

答案 2 :(得分:3)

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);
    }
}