0

MainActivity class Code which uses GestureDetector to get coordinate:

public class MainActivity extends AppCompatActivity implements GestureDetector.OnGestureListener,
GestureDetector.OnDoubleTapListener {

    DrawView drawView;
    private GestureDetectorCompat g1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        drawView = new DrawView(this);
        drawView.setBackgroundColor(Color.TRANSPARENT);
        setContentView(drawView);
        g1 = new GestureDetectorCompat(this,this);
        g1.setOnDoubleTapListener(this);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        g1.onTouchEvent(event);
        return super.onTouchEvent(event);
    }

    @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
        drawView.setXandY(e.getX(), e.getY());
        Log.v("id2","message2");
        return false;
    }

Code which uses this coordinate:

public class DrawView extends View {
    Paint paint = new Paint();
    static float x_touch = -1;
    static float y_touch = -1;
    static int [][] arr = new int[][]{{-1,-1,-1},{-1,-1,-1},{-1,-1,-1}};
    static int maxX = -1, maxY = -1;
    public DrawView(Context context) {
        super(context);
        super.setWillNotDraw(false);
        paint.setColor(Color.BLACK);
    }

    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Display mdisp = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
        Point mdispSize = new Point();
        mdisp.getSize(mdispSize);
        maxX = mdispSize.x;
        maxY = mdispSize.y;
        canvas.drawLine(maxX/3, 0, maxX/3, maxY, paint);
        canvas.drawLine(maxX*2/3, 0, maxX*2/3, maxY, paint);
        canvas.drawLine(0, maxY / 3, maxX, maxY / 3, paint);//This is first Horizontal line

        canvas.drawLine(0, maxY * 2 / 3, maxX, maxY * 2 / 3, paint); //This is second horizontal line

        Log.v("id1", "message1");
        paint.setTextSize(150f);
        if (x_touch>0 && y_touch>0) {
            if (x_touch < maxX/3 && y_touch < maxY/3)
                canvas.drawText("X", maxX/6, maxY/6, paint);
            else if (x_touch>maxX/3 && x_touch<2*maxX/3 && y_touch<maxY/3)
                canvas.drawText("X", maxX/2, maxY/6, paint);
            else if (x_touch>maxX*2/3 && y_touch<maxY/3)
                canvas.drawText("X", 5*maxX/6, maxY/6, paint);
            else if (x_touch<maxX/3 && y_touch>maxY/3 && y_touch<2*maxY/3)
                canvas.drawText("X", maxX/6, maxY/2, paint);
            else if (x_touch>maxX/3 && x_touch<2*maxX/3 && y_touch>maxY/3 && y_touch<2*maxY/3)
                canvas.drawText("X", maxX/2, maxY/2, paint);
            else if (x_touch>2*maxX/3 && y_touch>maxY/3 && y_touch<2*maxY/3)
                canvas.drawText("X", 5*maxX/6, maxY/2, paint);
            else if (x_touch<maxX/3 && y_touch>2*maxY/3)
                canvas.drawText("X", maxX/6, 5*maxY/6, paint);
            else if (x_touch>maxX/3 && x_touch<2*maxX/3 && y_touch>2*maxY/3)
                canvas.drawText("X", maxX/2, 5*maxY/6, paint);
            else if (x_touch>2*maxX/3 && y_touch>2*maxY/3)
                canvas.drawText("X", 5*maxX/6, 5*maxY/6, paint);
            Log.v("id3", "maxX="+Float.toString(maxX)+" maxY="+Float.toString(maxY)+
                    " x_touch="+Float.toString(x_touch)+" y_touch="+Float.toString(y_touch));
        }
    }

    public void setXandY(float x, float y) {
        x_touch = x;
        y_touch = y;
        this.invalidate();
    }
}

Clicking just above first horizontal line prints "X" below the first horizontal line and Clicking just above second horizontal line prints "X" below the second horizontal line.

Logcat shows that clicking just above first horizontal line does give a value greater than maxY/3.

EDIT: I tried removing titlebar from the app and its accuracy improved to some extent but still not very accurate.

nav_jan
  • 2,473
  • 4
  • 24
  • 42

1 Answers1

1

The problem is that you are using the MotionEvent received by the onTouchEvent of your Activity (documentation) so the coordinates you are receiving are Activity based instead of View based.

To solve your problem you can move the gesture detection to your DrawView:

public class DrawView extends View implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener {
    private GestureDetectorCompat g1;

    public DrawView(final Context context) {
        super(context);

        g1 = new GestureDetectorCompat(getContext(), this);
        g1.setOnDoubleTapListener(this);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        g1.onTouchEvent(event);
        return super.onTouchEvent(event);
    }

    @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
        setXandY(e.getX(), e.getY());
        Log.v("id2","message2");
        return false;
    }
}

Also, to receive touch events on your DrawView don't forget to make it clickable:

drawView.setClickable(true);

Edit based on the comments:

In this example the black X represents the touch.

enter image description here

When you receive the MotionEvent on the onTouchEvent of the View, the coordinates you receive are View related, so you will receive (124, 187).

When you receive the MotionEvent on the onTouchEvent of the Activity, the coordinates you receive are Activity related, so you will receive (324, 487).

When you draw on the View the coordinates are View related, so if you draw the coordinates received Activity related, you will draw on the red point.

antonio
  • 18,044
  • 4
  • 45
  • 61
  • Yes this fix works as magic. Thanks!! 50 reputation well spent!! – nav_jan Apr 20 '16 at 11:52
  • Can you please also explain why y-coordinate should vary if `MotionEvent` received by the `onTouchEvent` of `Activity` instead of `View` – nav_jan Apr 21 '16 at 04:40
  • Glad to help! I tried to explain it of the first paragraph but maybe it's not as clear as I would have liked. I have added an exaple. Hope it helps! – antonio Apr 21 '16 at 06:25
  • But in my case both Activity and View are of full screen. Aren't they ? – nav_jan Apr 21 '16 at 07:15
  • Yes, but in your case the `MotionEvent` received from the `Activity` also takes into account the notification bar (and title if you haven't removed it). You can try removing the title and notification bar and logging the `MotionEvent` coordinates received (see http://stackoverflow.com/questions/2868047/fullscreen-activity-in-android) – antonio Apr 21 '16 at 07:39
  • OK!! Thanks again. – nav_jan Apr 21 '16 at 08:40