Long Touch on a surfaceView ( android )

NioX5199 picture NioX5199 · Jul 13, 2010 · Viewed 7.6k times · Source

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.

Answer

Overmacht picture Overmacht · Apr 6, 2012

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 ;).