Android get bounding rectangle of a View

Android

Android Problem Overview


I'm implementing a drag and drop for an Android application. In order to know if the drop happens inside the drop target, I need to know the bounding rectangle of the drop target view. I would then see if the getRawX/Y() in the MotionEvent fall within this rect when I get the ACTION_UP action.

I realize I can call getLeft/Right/Top/Bottom() on the drop target view, but these are relative to the parent's container. It seems I need to know the "real" or raw values so i can compare them to the raw x, y in the MotionEvent.

Android Solutions


Solution 1 - Android

Yes, View.getLocationOnScreen() did the trick. For example,

private boolean isViewContains(View view, int rx, int ry) {
	int[] l = new int[2];
	view.getLocationOnScreen(l);
	int x = l[0];
	int y = l[1];
	int w = view.getWidth();
	int h = view.getHeight();

	if (rx < x || rx > x + w || ry < y || ry > y + h) {
		return false;
	}
	return true;
}

Solution 2 - Android

You can also use a Rect here:

private boolean isViewContains(...) {
    int[] l = new int[2];
    imageView.getLocationOnScreen(l);
    Rect rect = new Rect(l[0], l[1], l[0] + imageView.getWidth(), l[1] + imageView.getHeight());
    return rect.contains(rx, ry);
}

Less wordy, and possibly faster, but certainly (IMO) more readable.

Solution 3 - Android

This code takes into consideration, the perimeter of the Views involved and only returns true when the dragged View is fully inside the drop zone.

public boolean containsView(View dropZone, View draggedView){
	 // Create the Rect for the view where items will be dropped
	 int[] pointA = new int[2];
	 dropZone.getLocationOnScreen(pointA);
     Rect rectA = new Rect(pointA[0], pointA[1], pointA[0] + dropZone.getWidth(), pointA[1] + dropZone.getHeight());
	
     // Create the Rect for the view been dragged
     int[] pointB = new int[2];
     draggedView.getLocationOnScreen(pointB);
     Rect rectB = new Rect(pointB[0], pointB[1], pointB[0] + draggedView.getWidth(), pointB[1] + draggedView.getHeight());
     
     // Check if the dropzone currently contains the dragged view
     return rectA.contains(rectB);
}

Solution 4 - Android

Kotlin Extension solution

Here is a combination of extension getters you can add to quickly get the x/y coordinated or the bounding box of any view

val View.screenLocation
    get(): IntArray {
        val point = IntArray(2)
        getLocationOnScreen(point)
        return point
    }

val View.boundingBox
    get(): Rect {
        val (x, y) = screenLocation
        return Rect(x, y, x + width, y + height)
    }

Solution 5 - Android

Using getGlobalVisibleRect:

val rect = Rect()
view.getGlobalVisibleRect(rect)
val isContainedInView = rect.contains(x, y)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJeffrey BlattmanView Question on Stackoverflow
Solution 1 - AndroidJeffrey BlattmanView Answer on Stackoverflow
Solution 2 - AndroidtbmView Answer on Stackoverflow
Solution 3 - Androidkc ochibiliView Answer on Stackoverflow
Solution 4 - AndroidGiboltView Answer on Stackoverflow
Solution 5 - AndroidOmar AflakView Answer on Stackoverflow