Coordinates on touch


Last Updated:

  1. maest

    maest Member This Topic's Starter

    Joined:
    Aug 5, 2010
    Messages:
    23
    Likes Received:
    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.
     

    Advertisement
  2. jonbonazza

    jonbonazza Well-Known Member

    Joined:
    Jul 13, 2010
    Messages:
    1,934
    Likes Received:
    458
    Override the following method

    Code (Text):
    1.  
    2. @Override
    3. public boolean onTouchEvent(MotionEvent e)
    4. {
    5.          if(e.getAction() == MotionEvent.ACTION_DOWN)
    6.          {
    7.                  touchX = e.getX();
    8.                  touchY = e.getY();
    9.          }
    10.          return super.onTouchEvent(e);
    11. }
    12.  
    Where touchX and touchY are class variables defined as integers.
     
    maest likes this.
  3. maest

    maest Member This Topic's Starter

    Joined:
    Aug 5, 2010
    Messages:
    23
    Likes Received:
    2
    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 (Text):
    1. import android.app.Activity;
    2. import android.os.Bundle;
    3. import android.view.MotionEvent;
    4. import android.view.View;
    5. import android.widget.TextView;
    6.  
    7. public class touchCoord extends Activity {
    8.     /** Called when the activity is first created. */
    9.     @Override
    10.     public void onCreate(Bundle savedInstanceState) {
    11.         super.onCreate(savedInstanceState);
    12.         setContentView(R.layout.main);
    13.        
    14.        
    15.     final class TouchView extends TextView{
    16.         float x, y;
    17.         public boolean onTouchEvent(MotionEvent e)
    18.         {
    19.         x = e.getX();
    20.         y = e.getY();
    21.         this.setText(Float.toString(x)+"x"+Float.toString(y));
    22.         return super.onTouchEvent(e);
    23.    }
    24.     }
    25.    
    26.     TouchView tv = (TouchView) findViewById(R.id.view);
    27.     }
    28.    
    29. }

    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.
     
  4. jonbonazza

    jonbonazza Well-Known Member

    Joined:
    Jul 13, 2010
    Messages:
    1,934
    Likes Received:
    458
    Now, no. in your class that extends Activity, just implement that method.

    EDIT: It doesn't do ti for a specific view. it will do it for the whole screen.
     
  5. maest

    maest Member This Topic's Starter

    Joined:
    Aug 5, 2010
    Messages:
    23
    Likes Received:
    2
    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?
     
  6. maest

    maest Member This Topic's Starter

    Joined:
    Aug 5, 2010
    Messages:
    23
    Likes Received:
    2
    Sorry for double posting, the Edit button doesn't allow me to insert code.

    Here's what I've rewritten:

    Code (Text):
    1. import android.app.Activity;
    2. import android.os.Bundle;
    3. import android.view.MotionEvent;
    4. import android.view.View;
    5. import android.widget.TextView;
    6.  
    7. public class touchCoord extends Activity {
    8.     float x,y;
    9.     /** Called when the activity is first created. */
    10.     @Override
    11.     public void onCreate(Bundle savedInstanceState) {
    12.         x = 1;
    13.         y = 1;
    14.         super.onCreate(savedInstanceState);
    15.         setContentView(R.layout.main);
    16.        
    17.         TextView tv = (TextView) findViewById(R.id.view);
    18.         tv.setOnClickListener(new View.OnClickListener() {
    19.             public void onClick(View v)
    20.             {
    21.                 ((TextView) v).setText(Float.toString(x)+"x"+Float.toString(y));
    22.             }});
    23.     }
    24.    
    25.     public boolean onTouchEvent(MotionEvent e)
    26.     {
    27.              if(e.getAction() == MotionEvent.ACTION_DOWN)
    28.              {
    29.                      x = e.getX();
    30.                      y = e.getY();
    31.              }
    32.              return super.onTouchEvent(e);
    33.     }
    34.    
    35. }
    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.
     
  7. jonbonazza

    jonbonazza Well-Known Member

    Joined:
    Jul 13, 2010
    Messages:
    1,934
    Likes Received:
    458
    That is correct.

    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
     
    maest likes this.
  8. maest

    maest Member This Topic's Starter

    Joined:
    Aug 5, 2010
    Messages:
    23
    Likes Received:
    2
    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.
     
  9. jonbonazza

    jonbonazza Well-Known Member

    Joined:
    Jul 13, 2010
    Messages:
    1,934
    Likes Received:
    458
    Try putting @Override above the onTouchEvent function.
     
  10. maest

    maest Member This Topic's Starter

    Joined:
    Aug 5, 2010
    Messages:
    23
    Likes Received:
    2
    Code (Text):
    1. import android.app.Activity;
    2. import android.os.Bundle;
    3. import android.view.MotionEvent;
    4. import android.view.View;
    5. import android.widget.TextView;
    6.  
    7. public class touchCoord extends Activity {
    8.     float x,y;
    9.     /** Called when the activity is first created. */
    10.     @Override
    11.     public void onCreate(Bundle savedInstanceState) {
    12.         x = 1;
    13.         y = 1;
    14.         super.onCreate(savedInstanceState);
    15.         setContentView(R.layout.main);
    16.        
    17.         TextView tv = (TextView) findViewById(R.id.view);
    18.         tv.setOnClickListener(new View.OnClickListener() {
    19.             public void onClick(View v)
    20.             {
    21.                 ((TextView) v).setText(Float.toString(x)+"x"+Float.toString(y));
    22.             }});
    23.     }
    24.    
    25.     @Override
    26.     public boolean onTouchEvent(MotionEvent e)
    27.     {
    28.              
    29.                      x = e.getX();
    30.                      y = e.getY();
    31.              
    32.              return super.onTouchEvent(e);
    33.     }
    34.    
    35. }
    Tried removing the if statement as well. Still no effect, it still refuses to update the values of x and y.
     
  11. id0001

    id0001 Well-Known Member

    Joined:
    Apr 20, 2010
    Messages:
    142
    Likes Received:
    23
    have you tried updating the textview directly to make sure the problem is not with the textview?
     
  12. maest

    maest Member This Topic's Starter

    Joined:
    Aug 5, 2010
    Messages:
    23
    Likes Received:
    2
    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?
     
  13. id0001

    id0001 Well-Known Member

    Joined:
    Apr 20, 2010
    Messages:
    142
    Likes Received:
    23
    maybe you need to return 'true' instead of 'super.onTouchEvent(e)'

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

    Code (Text):
    1. public boolean onTouchEvent(MotionEvent event) {
    2.     switch (event.getAction() & MotionEvent.ACTION_MASK) {
    3.     case MotionEvent.ACTION_DOWN:
    4.         this.timer = SystemClock.currentThreadTimeMillis();
    5.         this.dragStart.set(event.getX(0), event.getY(0));
    6.         this.dragSnap.set(0,0);
    7.         mode = MODE_DRAG;
    8.         break;
    9.     //! code removed.
    10.     }
    11.  
    12.     return true;
    13. }
     
  14. maest

    maest Member This Topic's Starter

    Joined:
    Aug 5, 2010
    Messages:
    23
    Likes Received:
    2
    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?
     
  15. maest

    maest Member This Topic's Starter

    Joined:
    Aug 5, 2010
    Messages:
    23
    Likes Received:
    2
    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?
     
  16. id0001

    id0001 Well-Known Member

    Joined:
    Apr 20, 2010
    Messages:
    142
    Likes Received:
    23
    consumed means that you have used the event and that no other code may use the event after you have.

    Why do you even use an onClick listener?
    You could update the textview from you onTouchEvent method.
     
  17. maest

    maest Member This Topic's Starter

    Joined:
    Aug 5, 2010
    Messages:
    23
    Likes Received:
    2
    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 (Text):
    1. package bogdan.touchCoord;
    2.  
    3. import android.app.Activity;
    4. import android.os.Bundle;
    5. import android.view.MotionEvent;
    6. import android.widget.TextView;
    7.  
    8. public class touchCoord extends Activity {
    9.     float x,y;
    10.     TextView tv;
    11.     /** Called when the activity is first created. */
    12.     @Override
    13.     public void onCreate(Bundle savedInstanceState) {
    14.         x = 1;
    15.         y = 2;
    16.         super.onCreate(savedInstanceState);
    17.         setContentView(R.layout.main);
    18.        
    19.         tv = (TextView) findViewById(R.id.view);
    20.         tv.setText("Coordinates here.");
    21.     }
    22.    
    23.     @Override
    24.     public boolean onTouchEvent(MotionEvent e)
    25.     {
    26.         tv.setText(Float.toString(x)+"x"+Float.toString(y));
    27.         x = e.getX();
    28.         y = e.getY();
    29.              
    30.              return true;
    31.     }
    32.    
    33. }
    Thank you for your help.
     
  18. maest

    maest Member This Topic's Starter

    Joined:
    Aug 5, 2010
    Messages:
    23
    Likes Received:
    2
    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.
     
  19. id0001

    id0001 Well-Known Member

    Joined:
    Apr 20, 2010
    Messages:
    142
    Likes Received:
    23
    if you can get the location and size of your textview you could put that code into your onTouchEvent. You would have to check if the touching point is within the boundry's of the textview and react according to the result.
     
  20. jonbonazza

    jonbonazza Well-Known Member

    Joined:
    Jul 13, 2010
    Messages:
    1,934
    Likes Received:
    458
    Sorry, I have been MIA lately. been busy over the weekend. At any rate, id0001 is correct, you would have to manually handle that in the onTouchEvent() method. As far as I know, there is no other way. I could be wrong though (and hopefully I am!).
     

Share This Page

Loading...