androidgestures

Handling Tap and Pinch Gesture on Same View


I am trying to implement both Gestures (Tap and Scale/Pinch) on the Same View.
Here is my onTouchListener Code:

@Override
public boolean onTouch(View v, MotionEvent event) {
    // TODO Auto-generated method stub

    int touchCount = event.getPointerCount();

    switch(event.getAction())
    {

        case MotionEvent.ACTION_DOWN:
        {
            if(touchCount==1)
            {
                //do Autofocus here
                Log.v(TAG, "touchCount == 1");
                gestureDetector.onTouchEvent(event);
            }
        }
        break;

        case MotionEvent.ACTION_MOVE:
        {
            if(touchCount==2)
            {
                //scale gesture
                Log.v(TAG, "touchCount == 2");
                scaleGestureDetector.onTouchEvent(event);
            }   
        }
        break;

     }


Gestures Code:

    scaleGestureDetector = new ScaleGestureDetector(getActivity(), new ScaleGestureListener()); 
    gestureDetector = new GestureDetector(new Gesture());

private class ScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        float scale = detector.getScaleFactor();

        Log.v(TAG, "scale = "+scale);

        return true;
    }

    @Override
    public void onScaleEnd(ScaleGestureDetector detector) {
        // TODO Auto-generated method stub
        super.onScaleEnd(detector);
    }
}

private class Gesture extends GestureDetector.SimpleOnGestureListener
{

    @Override
    public boolean onDown(MotionEvent event) {
        // TODO Auto-generated method stub

        Log.v(TAG, "onDown ");

        return super.onDown(event);
    }
};


Problem: It always Triggers Down Event in my Gesture listener, even when i try to use Pinch Gesture.

Any help is highly appreciated.


Solution

  • I have solved this problem with the following logic:

    I have taken a flag isPinchInProgress and executed the code in my Tap Gesture Listener with some Delay, checking if the isPinchInProgress Flag is true or false.

    boolean isPinchInProgress = false;
    
    private class ScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
    
        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {
            // TODO Auto-generated method stub
    
            Log.d(TAG, "scaling started !");
    
            isPinchInProgress = true;
    
            return true;
    
        }
    
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
    
            return true;
        }
    
        @Override
        public void onScaleEnd(ScaleGestureDetector detector) {
            // TODO Auto-generated method stub
    
            Log.d(TAG, "scaling end !");
    
            isPinchInProgress = false;
    
            super.onScaleEnd(detector);
        }
    }
    
    private class Gesture extends GestureDetector.SimpleOnGestureListener
    {
    
        @Override
        public boolean onSingleTapConfirmed(final MotionEvent event) {
            // TODO Auto-generated method stub
    
            Log.v(TAG, "onSingleTapConfirmed ");
    
                new Handler().postDelayed(new Runnable() {
    
                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        if(!isPinchInProgress)
                        {
                          //My code to be executed
                        }
                    }
                }, 270);
    
            return true;
        }
    
        @Override
        public boolean onDown(MotionEvent e) {
            // TODO Auto-generated method stub
    
            return onSingleTapConfirmed(e);
        }
    }
    
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // TODO Auto-generated method stub
    
        int touchCount = event.getPointerCount();
    
        if(v instanceof MY_CUSTOM_VIEW_CLASS)
        {
    
            switch(event.getAction())
            {
    
            case MotionEvent.ACTION_DOWN:
            {
                if(touchCount == 2)
                {
                    return false;
                }
                else if(touchCount==1)
                {
                    //do Autofocus here
                    Log.v(TAG, "touchCount == 1");
                    gestureDetector.onTouchEvent(event);
                    return true;
                }
            }
            break;
    
            case MotionEvent.ACTION_MOVE:
            {
                if(touchCount==2)
                {
                    //scale gesture
                    Log.v(TAG, "touchCount == 2");
    
                    scaleGestureDetector.onTouchEvent(event);
    
                    return true;
                }
                else if(touchCount == 1)
                {
                    return false;
                }
            }
            break;
    
            case MotionEvent.ACTION_UP:
            {
                scaleGestureDetector.onTouchEvent(event);
                return true;
            }
    
            }
    
        }
    
        return false;
    }
    

    I hope this helps anyone, who is facing the same problem.