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

Dav*_*Gin 17 android transformation android-view

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

在一个特定的情况下,我需要实现一个复杂的变换,它围绕一个遥远的枢轴点旋转,然后在不同的枢轴点上缩放.由于它们共享相同的轴心点,因此无法简单地使用setScaleX/Y和setRotationX/Y.

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

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

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

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

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

xtr*_*var 10

我也是在嘲笑我.这是我提出的最好的(超级hacky):

 MyAnimation animation = new MyAnimation(matrix);
 animation.setDuration(0);
 animation.setFillAfter(true);
 view.setAnimation(animation);
Run Code Online (Sandbox Code Playgroud)


小智 6

上面的动画解决方案可以工作,但是它会导致无限调用,applyTransformation从效率的角度来看,还有一些需要改进的地方。另外,如果您杀死动画,则所应用的矩阵对于视图而言并不是永久的,因此您不得不使其永久运行。这是一种不那么笨拙的替代方法,setMatrix每次调用invalidate()视图时只调用一次即可:

在父母视图构造函数中:

setStaticTransformationsEnabled(true);
Run Code Online (Sandbox Code Playgroud)

然后在体内:

    @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;
}
Run Code Online (Sandbox Code Playgroud)

只要invalidate()您想随时更新子矩阵,就可以调用它。


mes*_*mes 5

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);
    }
}
Run Code Online (Sandbox Code Playgroud)