Search code examples
androidviewgesture-recognition

Trouble implementing OnGestureListere on a custom view


I want to implement a listener for my view. I want to detect a simple click a double tap and a long press and that is all. Here is the code I wrote (pertinent parts only):

public class BoardView extends View implements OnGestureListener, OnDoubleTapListener{

    //My functions and code. 

@Override 
public boolean onTouchEvent(MotionEvent event){ 
    Toast t = Toast.makeText(this.getContext(), "I'm touched", Toast.LENGTH_SHORT);
    t.show();
    System.err.println("On Touch");
    return super.onTouchEvent(event);
}

public void onLongPress(MotionEvent event) {
    Toast t = Toast.makeText(this.getContext(), "I get it, stop touching me!!!", Toast.LENGTH_SHORT);
    t.show();       
    System.err.println("Long Press");
    //Log.d(DEBUG_TAG, "onLongPress: " + event.toString()); 
}

@Override
public void onGesture(GestureOverlayView overlay, MotionEvent event) {

}

@Override
public void onGestureCancelled(GestureOverlayView overlay, MotionEvent event) {

}

@Override
public void onGestureEnded(GestureOverlayView overlay, MotionEvent event) {


}

@Override
public void onGestureStarted(GestureOverlayView overlay, MotionEvent event) {
    // TODO Auto-generated method stub

}

@Override
public boolean onDoubleTapEvent(MotionEvent e) {
    return false;
}

@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
    // TODO Auto-generated method stub
    return false;
}

@Override
public boolean onDoubleTap(MotionEvent e) {
    Toast t = Toast.makeText(this.getContext(), "Soy double the joy", Toast.LENGTH_SHORT);
    t.show();
    System.err.println("Double Tap");
    return true;
}
}

I detect the touch perfectly but not the double tap or the long press.... what am I doing wrong?

EDIT: Following one of the answers I wrote the following code:

private class Gestures extends SimpleOnGestureListener{

    public Gestures(){          
    }

    public void onTouchEvent(MotionEvent event){
        System.err.println("Touch Even gestures");
    }
     @Override
        public void onLongPress(MotionEvent event) {
            System.err.println("Long Press");
        }

     @Override
        public boolean onDoubleTap(MotionEvent event) {
         System.err.println("Double Tap");
            return true;
        }

}

Gestures gdetector = new Gestures();

This is before my BoardView constructor. Then as I understand I should have done:

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

However I only got the simple touch detected....


Solution

  • You should simply extend GestureDetector.SimpleOnGestureListener in some inner class of your view and override methods you want(double tap, long press etc.) and you can handle these gestures with gesture detector containing this listener.

    Example view could look like this:

    public class GestureView extends View
    {
        private GestureDetector mGestureDetector;
    
        //only one constructor for shorter code, in final code all should be presented
        public GestureView(Context context, AttributeSet attrs)
        {
            super(context, attrs);
    
            final MyGestureListener myGestureListener = new MyGestureListener();
            mGestureDetector = new GestureDetector(context, myGestureListener);
            mGestureDetector.setOnDoubleTapListener(myGestureListener);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event)
        {
            return mGestureDetector.onTouchEvent(event) || super.onTouchEvent(event);
        }
    
        private class MyGestureListener extends GestureDetector.SimpleOnGestureListener
        {
            @Override
            public boolean onDown(MotionEvent event)
            {
                return true;
            }
    
            @Override
            public void onLongPress(MotionEvent e)
            {
                //your code here
            }
    
            @Override
            public boolean onDoubleTap(MotionEvent e)
            {
                //your code here return true if event handled
                return super.onDoubleTap(e);
            }
    
            //this can be taken as click
            @Override
            public boolean onSingleTapConfirmed(MotionEvent e)
            {
                //your code here return true if event handled
                return super.onSingleTapConfirmed(e);
            }
        }
    }
    

    If you want just to add gesture detector to some other view, you can simply call its onTouch method from onTouchListener like

    view.setOnTouchListener(new View.OnTouchListener()
    {
        @Override
        public boolean onTouch(View v, MotionEvent event)
        {
            return gestureDetector.onTouchEvent(event);
        }
    });