如何在转换矩阵后得到视图的正确边界

时间:2011-11-11 15:48:25

标签: android

我有自定义视图,我在其中使用转换。到目前为止一切顺利,像setRotationY()setScaleX()setTranslationY()或甚至getMatrix()这样的功能按预期工作,我能够操纵我的视图并且显示正常。 我撞墙的地方是,之后有很多功能表现得很奇怪。例如getHitRect()之类的函数返回完全奇怪的值!这对我的触摸事件没有帮助。

我试图重载该功能,但它仍远未使用,特别是在使用旋转或缩放时(翻译工作正常)。我认为这与矩阵以子坐标表示的事实有关,那么如何在父坐标中得到它呢?

@Override
    public void getHitRect(Rect outRect){

        RectF rect = new RectF(); 
        rect.top = (float) this.getTop(); 
        rect.bottom = (float) this.getBottom(); 
        rect.left = (float) this.getLeft(); 
        rect.right = (float) this.getRight();      

    this.getMatrix().mapRect(rect);
        rect.round(outRect);
    }

我可以直接从某个功能获得更直接的值吗?像新的高度,宽度,顶部或底部。

1 个答案:

答案 0 :(得分:9)

当覆盖ViewGroup的“getChildStaticTransformation”方法或甚至使用转换函数时,例如setRotationY()setScaleX()setTranslationY()getMatrix()(可从API 11获得)只影响渲染矩阵。因此,您的自定义子视图将返回远离您的孩子画画的边界“矩形”。这在大多数情况下不是问题,但是当你开始愿意点击它时......麻烦就开始了......这就是我解决这个问题的方法。我相信可能会有更好的方法,但由于我在这里没有找到很多关于这个问题的东西。

在ViewGroup重载中:

public interface Itransformable {
    public void setTransformationMatrix(Matrix trsMatrix);
}

@Override
protected boolean getChildStaticTransformation(View child, Transformation t) {
    if (child instanceof Itransformable){   
        t.clear();
        t.setTransformationType(Transformation.TYPE_MATRIX);
        ...
        // Do whatever transformation you want here
        ...
        ((Itransformable)child).setTransformationMatrix(t.getMatrix());
        return true;
    } else {
        return false;
    }
}

以下是儿童自定义视图: 请注意,我不是直接将转换矩阵存储在自定义视图中,而是存储转换后的Rect。如果你想要存储矩阵(即稍后转换像点......),你可能需要克隆它,因为矩阵将以某种奇怪的方式被改变,就像它是循环或其他东西。

public class MyCustomView extends View implements MyViewGroup.Itransformable{

private Rect mViewRect = null;

public void setTransformationMatrix(Matrix trsMatrix){
    if (trsMatrix!=null){
        RectF rect = new RectF();
        rect.top = 0;
        rect.bottom = (float) this.getHeight(); 
        rect.left = 0; 
        rect.right = (float) this.getWidth();  

        trsMatrix.mapRect(rect);
        rect.offset((float) this.getLeft(), (float) this.getTop());

        if (mViewRect == null) mViewRect = new Rect();
        rect.round(mViewRect);
    }
}

public Rect getTransformatedRect() {
    if (mViewRect!=null){
        // OutOfScreen WorkArround - As the view is not Displayed, mViewRect doesn't get updated.
        if(getRight() < 0 || getLeft() > mParentWidth){
            return new Rect(getLeft(),getTop(),getRight(),getBottom());
        } else {
            return mViewRect;
        }
    } else {
        return new Rect(getLeft(),getTop(),getRight(),getBottom());
    }
}

@Override
public void getHitRect(Rect outRect){

    if (mViewRect == null){
        super.getHitRect(outRect);
    } else {
        outRect.set(getTransformatedRect());
    }
}