Search code examples
javaandroidkotlinandroid-relativelayoutontouchlistener

How to get the x,y coordinates of touch on a View (textview, button etc) in Android


I have the following structure in android

  • Relative Layout 1 (background color black)
    • Relative Layout 2 (background color white)
      • TextView 1 (background color red)

enter image description here

when a user touches on my textview(MotionEvent.ACTION_DOWN), I want to get the x&y coordinates of touch.

I'm able to get the touch coordinates with the following code:

title_text_view.setOnTouchListener (object : View.OnTouchListener {

        override fun onTouch (view: View, event: MotionEvent): Boolean {

            if (event.actionMasked == MotionEvent.ACTION_DOWN) {

                    var x:Float
                    var y:Float

                x = view.x + event.x
                y = (view.parent as ViewGroup).y + view.y + event.y

                
            }

            // returning false indicates that the listener has not consumed the touch event
            // If no other listener consumes the event, the system will handle it according to the default behavior
            return false
        }
    })

As you can see, to compute my Y coordinate i have to add (event.y + view.y + (view.parent as ViewGroup).y)

let's say I have click on black dot (between click me, see image), wrt to the text ClickMe, (0,0) will start from top left red corner so I can get x,y based on that (event.x & event.y), but to get it wrt to screen's 0,0 i.e top left black corner I need to find View.y of parent (white part i.e. 50) and View.y of parent's parent (black part i.e. 900).

then compute actual y: 107+50+900

but I can have a more complex hierarchical structure i.e. relative layouts inside relative layouts and then finally a textview. Is there any other way to get the x,y coordinates directly without this computation?

PS: I know I can a setOnTouchListener on the topmost relative layout and get x,y and i'll get x,y but i have to set event listener on my textview only.


Solution

  • In the view class you have View.getLocationOnScreen(). You don't mention it directly, but you probably want to transform touch location from local to touched view to relative to screen. But be aware that this means the entire device screen, as is described in documentation:

    Gets the coordinates of this view in the coordinate space of the device screen, irrespective of system decorations and whether the system is in multi-window mode.

    If on the other hand you want to transform coordinates relative to Activity, then use View.getLocationInWindow()

    Gets the coordinates of this view in the coordinate space of the > window that contains the view, irrespective of system decorations.

    Both methods will fill an array of two integers which you can add to your event.x,event.y coordinates which are in touched view coordinates.

    For example, in your code:

    if (event.actionMasked == MotionEvent.ACTION_DOWN) {
      val location = IntArray(2)
      view.getLocationOnScreen(location)
      // view.getLocationInWindow(location)
    
      val x = location[0] + event.x
      val y = location[1] + event.y
    }