I'm making a game on Android and I need to do certain actions when the users attempts a long press on the screen. Unfortunately I haven't found any methods that works directly with a custom SurfaceView, feel free to tell me if such a method exists :)
So I decided to try and implement a long touch detection from the onTouch event listener.
here is my code:
@Override
public boolean onTouch(View v, MotionEvent event)
{
long touchDuration = 0;
if ( event.getAction() == MotionEvent.ACTION_DOWN )
{
//Start timer
touchTime = System.currentTimeMillis();
}else if ( event.getAction() == MotionEvent.ACTION_UP )
{
//stop timer
touchDuration = System.currentTimeMillis() - touchTime;
if ( touchDuration < 800 )
{
onShortTouch(event,touchDuration);
}else
{
onLongTouch(event,touchDuration);
}
}
}
return true;
This works, but I can detect if the press was a long press or not only when the user stops touching the phone. So it's not exactly what I want. I would prefer if a timer would start when the user first touches the screen then once 800 ms is elapsed the LongTouch() method is called. In other words, I don't want to have to check how long has elapsed when ACTION_UP since ACTION_DOWN. I believe I should use a thread for the said timer but I can't make it work. When using the following code, the debug message is displayed as soon as I touch the screen:
@Override
public boolean onTouch(View v, MotionEvent event)
{
long touchDuration = 0;
TouchThread touchThread = new TouchThread();
if ( event.getAction() == MotionEvent.ACTION_DOWN )
{
//Start timer
touchTime = System.currentTimeMillis();
touchThread.setEvent(event);
touchThread.run();
}
return true;
}
private class TouchThread extends Thread
{
public MotionEvent event = null;
public void setEvent(MotionEvent e)
{
event = e;
}
@Override
public void run()
{
long startTime = System.currentTimeMillis();
long time = 0;
while(event.getAction() == MotionEvent.ACTION_DOWN)
{
time = System.currentTimeMillis() - startTime;
if( time > 800 )
{
System.out.println("LOOONG CLICK!!");
return;
}
}
}
}
Has anyone got any idea ? An other solution would also be welcome.
Thanks.
It's quite easy, actually. In your view's constructor, do this:
setOnLongClickListener(new View.OnLongClickListener()
{
public boolean onLongClick(View v) {
Log.v( "debug", "LONG CLICK!" );
return true;
}
}
);
Then override onTouchEvent:
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
}
And you're set ;).
A nice option when you also want to do some manual event processing is the GestureDetector class: http://developer.android.com/reference/android/view/GestureDetector.html
How I use it is to make a GestureDetector instance in the constructor, implement the methods I'm interested in, and then at the start of the onTouchEvent() method do something like:
if (gestureDetector.onTouchEvent(event)) {
return true;
}
Which then means in most cases when a gesture is detected that aborts the rest of your touch handling. However, long press is a little different because the long press method doesn't return a value. In this case I just have a boolean somewhere that I set when long press is triggered that I check later in the touch event handling method if necessary.
One thing you can do is set the OnLongClickListener on your SurfaceView.
mySurfaceView.setOnLongClickListener(l);
Then in your SurfaceView, you need to override the onTouchEvent :
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
return true;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With