简体   繁体   中英

How to find element in View by coordinates x,y Android

If i know coordinates(X,Y) pixel (by OnTouchEvent method and getX(),getY) how i can find element ex. button or text etc.... by use X,Y

You could use getHitRect(outRect) of each child View and check if the point is in the resulting Rectangle. Here is a quick sample.

for(int _numChildren = getChildCount(); --_numChildren)
{
    View _child = getChildAt(_numChildren);
    Rect _bounds = new Rect();
    _child.getHitRect(_bounds);
    if (_bounds.contains(x, y)
        // In View = true!!!
}

Hope this helps,

FuzzicalLogic

A slightly more complete answer that accepts any ViewGroup and will recursively search for the view at the given x,y.

private View findViewAt(ViewGroup viewGroup, int x, int y) {
    for(int i = 0; i < viewGroup.getChildCount(); i++) {
        View child = viewGroup.getChildAt(i);
        if (child instanceof ViewGroup) {
            View foundView = findViewAt((ViewGroup) child, x, y);
            if (foundView != null && foundView.isShown()) {
                return foundView;
            }
        } else {
            int[] location = new int[2];
            child.getLocationOnScreen(location);
            Rect rect = new Rect(location[0], location[1], location[0] + child.getWidth(), location[1] + child.getHeight());
            if (rect.contains(x, y)) {
                return child;
            }
        }
    }

    return null;
}

The same solution as https://stackoverflow.com/a/10959466/2557258 but in kotlin:

fun ViewGroup.getViewByCoordinates(x: Float, y: Float) : View? {
    (childCount - 1 downTo 0)
        .map { this.getChildAt(it) }
        .forEach {
            val bounds = Rect()
            it.getHitRect(bounds)
            if (bounds.contains(x.toInt(), y.toInt())) {
                return it
            }
        }
    return null
}

Modification of of the answer @Luke provided. Difference being using getHitRect rather than getLocationOnScreen . I found getLocationOnScreen to be inaccurate on what view was being selected. Also converted the code to Kotlin and made it an extension on ViewGroup :

/**
 * Find the [View] at the provided [x] and [y] coordinates within the [ViewGroup].
 */
fun ViewGroup.findViewAt(x: Int, y: Int): View? {
    for (i in 0 until childCount) {
        val child = getChildAt(i)

        if (child is ViewGroup) {
            val foundView = child.findViewAt(x, y)
            if (foundView != null && foundView.isShown) {
                return foundView
            }
        } else {
            val rect = Rect()

            child.getHitRect(rect)

            if (rect.contains(x, y)) {
                return child
            }
        }
    }
    return null
}

Android use dispatchKeyEvent/dispatchTouchEvent to find the right view to handle key/touch event, it's a complex procedure. Since there could be many views cover the (x, y) point.

But it's simple if you just want to find the most topside view that cover the (x, y) point.

1 Use getLocationOnScreen() to get the absoulte position.

2 Use getWidth(), getHeight() to figure out whether the view cover the (x, y) point.

3 Cacluate the level of view in whole view tree. (Call getParent() recursively or use some search method)

4 Find the view that both cover the point and have the biggest level.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM