25

I want to intercept the touch events on my parent view with onInterceptTouchEvent (MotionEvent ev).

From there I want to know which view was clicked in order to do other things, is there any way to know which view was clicked from that motion event received?

Suragch
  • 364,799
  • 232
  • 1,155
  • 1,198
htafoya
  • 15,392
  • 10
  • 62
  • 83

3 Answers3

80

Well for anyone who wants to know what I did ... i couldn't. I did a workaround to just know if my specific view component was clicked, so I could only end with this:

   if(isPointInsideView(ev.getRawX(), ev.getRawY(), myViewComponent)){
    doSomething()
   }

and the method:

/**
 * Determines if given points are inside view
 * @param x - x coordinate of point
 * @param y - y coordinate of point
 * @param view - view object to compare
 * @return true if the points are within view bounds, false otherwise
 */
public static boolean isPointInsideView(float x, float y, View view){
    int location[] = new int[2];
    view.getLocationOnScreen(location);
    int viewX = location[0];
    int viewY = location[1];

    //point is inside view bounds
    if(( x > viewX && x < (viewX + view.getWidth())) &&
            ( y > viewY && y < (viewY + view.getHeight()))){
        return true;
    } else {
        return false;
    }
}

However this only works for known views in the layout that you can pass as parameter, I still can't get the clicked view just by knowing the coordinates. You may search for all views in the layout though.

htafoya
  • 15,392
  • 10
  • 62
  • 83
  • 9
    private boolean isPointInsideView(float x, float y, View view) { Rect rect = new Rect(); view.getDrawingRect(rect); return rect.contains((int) x, (int) y); } – etienne Oct 26 '11 at 10:56
  • Suggestion: great method candidate to be made static. – m0skit0 Sep 07 '12 at 11:59
  • 6
    @etienne, please note that getDrawingRect() returns information about the drawing rect shown inside of a scroll view. It does not work if you want to get the rect of a view that is nested in another view. htafoya's solution works as expected. – sulai Nov 22 '12 at 13:43
  • @htafoya you know how to get current view's starting coordinates because it gives different coordinates if i clicked same view at different place... :( .. – Aniket Jun 18 '13 at 15:40
  • @Aniket viewX and viewY will have those values. – htafoya Aug 10 '14 at 19:40
  • I've had to modify the method to get real coordinates of view by view.getX() and view.getY(). the getLocationOnScreen didn't work for me – Apollo Jul 17 '15 at 10:10
  • @Apollo that's interesting ,`view.getX()` and `view.getY()` does not work for me,`view.getLocationOnScreen` works. – zionpi Jul 31 '15 at 03:01
  • @zionpi my views are inside a linearlayout vertical, inside a horizontal linearlayout, inside a linearlayout vertical, inside a realtivelayout.... And i have a swipe recognizer on the parent, and a tap recognizer on the child... My system is certainly in fault :) – Apollo Jul 31 '15 at 09:00
  • view.getLocationOnScreen didn't really work for me - I think it may return the center coordinates of the view, so the click has to be in the bottom right corner of the view for the test to return true, so the bounds check in this example is wrong. Instead, use this test: (x >= view.getLeft() && x <= view.getRight()) && (y >= view.getTop() && y <= view.getBottom()). – gjgjgj Mar 23 '17 at 23:49
4

A simple way for getting the touched view is to set an OnTouchListener to the individual views and store the view in a class variable of the activity. Returning false will make the input event available to the method onTouchEvent() of the activity, where you can easily handle all the touch events (also the ones of your parent view).

myView.setOnTouchListener(new OnTouchListener() {
    public boolean onTouch(View v, MotionEvent event) {
    touchedView = myView;
    return false;
    }
}); 


@Override
public boolean onTouchEvent(MotionEvent event) {


    switch (event.getAction()) {

        case MotionEvent.ACTION_UP:

            if(touchedView!=null) {
                doStuffWithMyView(touchedView);
            ....
            ....
4

Just to make method of htafoya simpler:

/**
* Determines if given points are inside view
* @param x - x coordinate of point
* @param y - y coordinate of point
* @param view - view object to compare
* @return true if the points are within view bounds, false otherwise
*/
private boolean isPointInsideView(float x, float y, View view) {
    int location[] = new int[2];
    view.getLocationOnScreen(location);
    int viewX = location[0];
    int viewY = location[1];

    // point is inside view bounds
    return ((x > viewX && x < (viewX + view.getWidth())) &&
            (y > viewY && y < (viewY + view.getHeight())));
}
schmidt9
  • 4,021
  • 1
  • 19
  • 29
  • Repeating my comment from above: view.getLocationOnScreen didn't really work for me - I think it may return the center coordinates of the view, so the click has to be in the bottom right corner of the view for the test to return true, so the bounds check in this example is wrong. Instead, use this test: (x >= view.getLeft() && x <= view.getRight()) && (y >= view.getTop() && y <= view.getBottom()). – gjgjgj Mar 23 '17 at 23:50