Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android onTouchEvent Coordinates Skip around

I my app, I have an element that requires the user to move it around on the screen, and to do this I am using a RelativeLayout and on onTouchListener.

The problem that I am having, is that inside of my onTouchListener, I am getting some weird results for getX() and getY().

I added the following line of code into my onTouch() -> ACTION_MOVE block:

Log.v("example", "Touch: {x:" + event.getX() + " } {y:" + event.getY() + "}");

Below are my LogCat results.

04-29 03:16:11.000: V/myApp(24188): Touch Down!
04-29 03:16:11.057: V/myApp(24188): Touch: {x:69.78699 } {y:107.774216}
04-29 03:16:11.103: V/myApp(24188): Touch: {x:77.86926 } {y:173.37648}
04-29 03:16:11.158: V/myApp(24188): Touch: {x:69.78699 } {y:108.781845}
04-29 03:16:11.205: V/myApp(24188): Touch: {x:77.86926 } {y:174.38597}
04-29 03:16:11.463: V/myApp(24188): Touch: {x:69.78699 } {y:109.64778}
04-29 03:16:11.502: V/myApp(24188): Touch: {x:77.86926 } {y:175.62172}
04-29 03:16:11.596: V/myApp(24188): Touch: {x:69.23099 } {y:109.40666}
04-29 03:16:11.654: V/myApp(24188): Touch Up!

As you can see, moving my finger very slowly in a straight line, I get a jumpy result, where the correct coordinates are actually every other line.

This is resulting in my view jumping back and fourth between the desired position and the offset position as i drag it across the screen.

I have added in checks to be sure that I am only creating a single element, and this this listener is not being called from anywhere other than this single view.

Has anyone else seen this problem before, and have any insight as to what I can do to fix it?

EDIT

View.OnTouchListener onTouch = new View.OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {

        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.d("example", "Touch down");
            break;

        case MotionEvent.ACTION_UP:
            Log.d("example", "Touch up");
            break;

        case MotionEvent.ACTION_MOVE:
            Log.v("example", "Touch: {x:" + event.getX() + " } {y:" + event.getY() + "}");
        }

        return true;    
    }
};
like image 877
Matt Clark Avatar asked Apr 29 '13 07:04

Matt Clark


3 Answers

I was able to solve this problem by using event.getRawX(), and event.getRawY().

like image 122
Matt Clark Avatar answered Sep 18 '22 23:09

Matt Clark


Do you return true inside onTouch() after processing the ACTION_MOVE event? Moreover, as the Android official Reference explains, "For efficiency motion events may batch together multiple movement samples within a single object". So you should use getX() and getY() only to retrieve the last coordinates. To access earlier coordinates you can use the methods getHistoricalX(int) and getHistoricalY(int). For more informations, read the official reference.

like image 45
user2302436 Avatar answered Sep 18 '22 23:09

user2302436


MotionEvent will sometimes return absolute X and Y coordinates relative to the view, and sometimes relative coordinates to the previous motion event.

getRawX() and getRawY() that is guaranteed to return absolute coordinates, relative to the device screen.



While getX() and getY(), should return you coordinates, relative to the View, that dispatched them.

reason behind

@Matt Clark answer

like image 25
Zar E Ahmer Avatar answered Sep 21 '22 23:09

Zar E Ahmer