Search code examples
androidviewdrawboundsrect

Get draw bounds/rect of a view


I'm developing an app where a lot of views can be rotated - it's something like a map of physical objects. I have to detect when 2 objects (all objects are rectangles/squares) are overlapping and if a user has performed a single/double/long tap on an object. For this reason I need to know the drawing bounds of a view.

Let's look at the example image bellow - the green rectangle is rotated 45 degrees. I need to get the coordinates of the 4 corners of the green rectangle. If I use view.getHitRect() it returns the bounding box (marked in red) of the view, which is of no use to me.

Do you know how could I get the coordinates of the edges of a view?

The only solution I could think of is to subclass a View, manually store the initial coordinates of the corners and calculate their new values on every modification to the view - translation, scale and rotation but I was wondering if there is a better method.

P.S. The app should be working on Android 2.3 but 4.0+ solutions are also welcomed.

Example situation


Solution

  • Thanks to pskink I explored again the Matrix.mapPoints method and managed to get the proper coordinates of the corners of the rectangle.

    If you are running on Android 3.0+ you can easily get the view's matrix by calling myView.getMatrix() and map the points of interest. I had to use 0,0 for the upper left corner and getWidth(),getHeight() for the bottom right corner and map these coordinates to the matrix. After that add view's X and Y values to get the real values of the corners.

    Something like:

    float points[] = new float[2];
            points[0] = myView.getWidth();
            points[1] = myView.getHeight();
            myView.getViewMatrix().mapPoints(points);
    
            Paint p = new Paint();
            p.setColor(Color.RED);
            //offset the point and draw it on the screen
            canvas.drawCircle(center.getX() + points[0], center.getY() + points[1], 5f, p);
    

    If you have to support lower versions of Android you can use NineOldAndroids. Then I've copied and modified one of its internal methods to get the view's matrix:

    public Matrix getViewMatrix()
    {
        Matrix m = new Matrix();
        Camera mCamera = new Camera();
    
        final float w = this.getWidth();
        final float h = this.getHeight();
        final float pX = ViewHelper.getPivotX(this);
        final float pY = ViewHelper.getPivotY(this);
    
        final float rX = ViewHelper.getRotationX(this);;
        final float rY = ViewHelper.getRotationY(this);
        final float rZ = ViewHelper.getRotation(this);
        if ((rX != 0) || (rY != 0) || (rZ != 0)) 
        {
            final Camera camera = mCamera;
            camera.save();
            camera.rotateX(rX);
            camera.rotateY(rY);
            camera.rotateZ(-rZ);
            camera.getMatrix(m);
            camera.restore();
            m.preTranslate(-pX, -pY);
            m.postTranslate(pX, pY);
        }
    
        final float sX = ViewHelper.getScaleX(this);
        final float sY = ViewHelper.getScaleY(this);;
        if ((sX != 1.0f) || (sY != 1.0f)) {
            m.postScale(sX, sY);
            final float sPX = -(pX / w) * ((sX * w) - w);
            final float sPY = -(pY / h) * ((sY * h) - h);
            m.postTranslate(sPX, sPY);
        }
    
        m.postTranslate(ViewHelper.getTranslationX(this), ViewHelper.getTranslationY(this));
    
        return m;
    }
    

    I've put this method in an overloaded class of a view (in my case - extending TextView). From there on it's the same as in Android 3.0+ but instead of calling myView.getMatrix() you call myView.getViewMatrix().