• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

Apps Coordinates on touch

maest

Newbie
Aug 5, 2010
23
2
Hi,

How should one go about if one wants to get the coordinates of where the user is touching the screen? Do all Views support this or is there a special type of View that allows you to know this?

Surface View looks like something that might be helpful here, but I don;t know how to obtain the coordinates of the touch.

EDIT: oups, SurfaceView isn't what I was looking for.
 
Hi,

How should one go about if one wants to get the coordinates of where the user is touching the screen? Do all Views support this or is there a special type of View that allows you to know this?

Surface View looks like something that might be helpful here, but I don;t know how to obtain the coordinates of the touch.

EDIT: oups, SurfaceView isn't what I was looking for.

Override the following method

Code:
@Override
public boolean onTouchEvent(MotionEvent e)
{
         if(e.getAction() == MotionEvent.ACTION_DOWN)
         {
                 touchX = e.getX();
                 touchY = e.getY();
         }
         return super.onTouchEvent(e);
}
Where touchX and touchY are class variables defined as integers.
 
  • Like
Reactions: maest
Upvote 0
Sorry, I don't think I've fully understood how to use this.

Am I supposed to just write a new class which extends View and implements the new method? That sounds a bit cumbersome. I've tried going that way, but I am required to provide a constructor as well, since TextView doesn't seem to have one.

Say I want to create a TextView that displays the coordinates where I touch it. The coordinates are updated on each touch.

Code:
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;

public class touchCoord extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        
    final class TouchView extends TextView{
        float x, y;
        public boolean onTouchEvent(MotionEvent e)
        {
        x = e.getX();
        y = e.getY();
        this.setText(Float.toString(x)+"x"+Float.toString(y));
        return super.onTouchEvent(e);
   }
    }
    
    TouchView tv = (TouchView) findViewById(R.id.view);
    }
    
}


I'm not sure that cast in the last line will work. If it won't, how am I supposed to override the method for that specific TextView?

Also, I don't see any other way to transmit x and y higher up other than defining them in the body of the activity.
 
Upvote 0
Oh, right, sorry. I did a search in the Reference documents and what I saw come up was the function as defined inside a View. Now I see there's an identical function defined for an Activity. Ok, so I can get the coordinates for the whole screen, if I reimplement it inside the Activity.

Just as a curiousity: What if I want to override it inside a view? Is there no other way than creating my own view and then creating such a view in the layout in main.xml?
 
Upvote 0
Sorry for double posting, the Edit button doesn't allow me to insert code.

Here's what I've rewritten:

Code:
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;

public class touchCoord extends Activity {
    float x,y;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        x = 1;
        y = 1;
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        TextView tv = (TextView) findViewById(R.id.view);
        tv.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v)
            {
                ((TextView) v).setText(Float.toString(x)+"x"+Float.toString(y));
            }});
    }
    
    public boolean onTouchEvent(MotionEvent e)
    {
             if(e.getAction() == MotionEvent.ACTION_DOWN)
             {
                     x = e.getX();
                     y = e.getY();
             }
             return super.onTouchEvent(e);
    }
    
}

However, when I run it, every time I click, the textView is rewritten but the value displayed is 1.0 x 1.0. Looks like onTouchEvent for the Activity is never evaluated.
 
Upvote 0
Ok, so I can get the coordinates for the whole screen, if I reimplement it inside the Activity.

That is correct.

Just as a curiousity: What if I want to override it inside a view? Is there no other way than creating my own view and then creating such a view in the layout in main.xml?

To my knowledge, there is no other way.
However, take that with a grain of salt as I have never really played around with making my own views (although the time for that is approaching at an ever-so-quick rate of speed).

H
 
  • Like
Reactions: maest
Upvote 0
Thanks for your help!

Could you take a look at the code in my last post and, if possible tell me why x and y never get reevaluated from 1?

Is it the emulator's fault, that it doesn't interpret clicks as being touches? Or did I do something wrong and onTouchEvent is never called.
 
Upvote 0
Code:
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;

public class touchCoord extends Activity {
    float x,y;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        x = 1;
        y = 1;
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        TextView tv = (TextView) findViewById(R.id.view);
        tv.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v)
            {
                ((TextView) v).setText(Float.toString(x)+"x"+Float.toString(y));
            }});
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent e)
    {
             
                     x = e.getX();
                     y = e.getY();
             
             return super.onTouchEvent(e);
    }
    
}

Tried removing the if statement as well. Still no effect, it still refuses to update the values of x and y.
 
Upvote 0
I'm not sure what you mean. The textView gets updated everytime I click, so the onClick method works. To choeck this, I've modified it so that at each click x gets incremented at each click (I've just added x++; inside the onClick method.) It works that way.

It's just that I think onTouchEvent is never called. Does it need some sort of listener?
 
Upvote 0
maybe you need to return 'true' instead of 'super.onTouchEvent(e)'

here's a snippet of my onTouchEvent for a pinchImageView class:

Code:
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction() & MotionEvent.ACTION_MASK) {
    case MotionEvent.ACTION_DOWN:
        this.timer = SystemClock.currentThreadTimeMillis();
        this.dragStart.set(event.getX(0), event.getY(0));
        this.dragSnap.set(0,0);
        mode = MODE_DRAG;
        break;
    //! code removed.
    }

    return true;
}
 
Upvote 0
Oh, right, I think I got it. So I looked through the Reference for Activty and it said there about the onTouchEvent that it only gets called if all the children views fail to catch the touch event. Now, I guess that onClick inside the TextView I use to display the coordinates is considered to cath the event, so the onTouchEvent in Activity is never called, if I click inside the TextView.

So I changed the size of TextView from fill_parent to wrap_content and initialized it with the string "Coordinates here." so it didn't completely disappear. Now, the program behaved as expected: When I clicked on the text view, it only got updated, but the coordinates did not change, and if I clicked somewhere else x and y got updated, but the text on screen didn't get updated since I wasn't calling onClick.

Now, my question is, how do I obtain the coordiantes if there's a View in the way? The Activity's onTouchEvent doesn't get called in this case. How can I get my hands on the MotionEvent?
 
Upvote 0
maybe you need to return 'true' instead of 'super.onTouchEvent(e)'

here's a snippet of my onTouchEvent for a pinchImageView class:

Code:
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction() & MotionEvent.ACTION_MASK) {
    case MotionEvent.ACTION_DOWN:
        this.timer = SystemClock.currentThreadTimeMillis();
        this.dragStart.set(event.getX(0), event.getY(0));
        this.dragSnap.set(0,0);
        mode = MODE_DRAG;
        break;
    //! code removed.
    }

    return true;
}

Sorry, missed that when I posted my reply. You're right insofar as I should return True, the spec says "Return true if you have consumed the event, false if you haven't.". I'm not sure what "consumed" means here... The way I guess this works is that all onTouchEvent return false so that the event gets passed up until it hits the View/Activity that handles it, when it returns true and the event doesn't get passed up.

This being said, I have no idea why the code isn't functioning. onClick in the listener attached to the view shouldn't count as consuming the event, should it?
 
Upvote 0
Ah, cool.

It worked after I decided to skip on the onClickListener. I guess that I can check for the event inside the onTouchEvent inside the Activity and update stuff from there. This method feels a bit clunky, but if I'll run into trouble down the road I'll ask for help.

Attached code:

Code:
package bogdan.touchCoord;

import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.widget.TextView;

public class touchCoord extends Activity {
    float x,y;
    TextView tv;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        x = 1;
        y = 2;
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        tv = (TextView) findViewById(R.id.view);
        tv.setText("Coordinates here.");
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent e)
    {
        tv.setText(Float.toString(x)+"x"+Float.toString(y));
        x = e.getX();
        y = e.getY();
             
             return true;
    }
    
}

Thank you for your help.
 
Upvote 0
Oh, actually, sorry for double posting but I have one more question. If using onClickListener means I can no longer read onTouchEvent when the touching event happens over the Text View, how would I go about things if in the above example I wanted to change the colour of the background everytime I clicked the TextView? Or if I needed any other effect to trigger when I click the TextView, for that matter.
 
Upvote 0

BEST TECH IN 2023

We've been tracking upcoming products and ranking the best tech since 2007. Thanks for trusting our opinion: we get rewarded through affiliate links that earn us a commission and we invite you to learn more about us.

Smartphones