Nastya Kizza
Nastya Kizza

Reputation: 362

Android: several gesture detectors on the same view

I have a TextView wrapped with ScrollView. The thing I need to do is to detect scale and common gestures (like tap, double tab and others) on my TextView. Also, I want some gestures to handle with standard handlers (scroll, for example). I just can't get the basics, I don't know what do I code for this. I made two detectors (ScaleGestureDetector and GestureDetector) and listeners for them. Also, I set onTouchListener for my TextView like this:

tw.setOnTouchListener(new OnTouchListener() {
    public boolean onTouch(View view, MotionEvent motionEvent) {
        if (!gestureDetector.onTouchEvent(motionEvent)) {
            scaleGestureDetector.onTouchEvent(motionEvent);
        };
        return true;
    }
});

No gestures are being detected. Every example which I googled operates with one detector. Could somebody help me out with the concept, how do I detect scale (or pinch zoom), double tap, single tap etc. on the same view?

Upvotes: 3

Views: 4260

Answers (3)

Suryavel TR
Suryavel TR

Reputation: 3786

  • Approach 1: You can see if Scale Gesture Detector is In Progress.
  • Approach 2: You can disable scroll gesture when you receive ACTION_POINTER_DOWN (secondary touch) action and reset it when you receive ACTION_POINTER_UP. (In this case scroll can happen only with one finger.)

Approach 1:

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
      if (mScaleGestureDetector.isInProgress()) {
          return false;
      }
    
      // Handle Scrolling Event.
      return true;
}

Approach 2:

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (event.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
        mShouldAllowScrolling++;
    }

    if (event.getActionMasked() == MotionEvent.ACTION_POINTER_UP) {
        mShouldAllowScrolling--;
    }

    boolean retVal = mScaleGestureDetector.onTouchEvent(event);
    if (mShouldAllowScrolling == 0) {
        retVal = mPanGestureListener.onTouchEvent(event) || retVal;
    }

    return retVal || super.onTouchEvent(event);
}

Upvotes: 1

Max Radin
Max Radin

Reputation: 427

One solution is to call onTouchEvent for both of your Detectors:

tw.setOnTouchListener(new OnTouchListener() {
    public boolean onTouch(View view, MotionEvent motionEvent) {
        gestureDetector.onTouchEvent(motionEvent);
        scaleGestureDetector.onTouchEvent(motionEvent);
        return true;
    }
});

This may, however, lead to undesirable behavior as both Detectors may simultaneously trigger; for example, one gesture may be identified as both a scale gesture and a scroll gesture.

To solve this, you can introduce a new variable scaleOngoing to keep track of whether or not a scale event is ongoing:

scaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureDetector.OnScaleGestureListener() {
    public void onScaleEnd(ScaleGestureDetector detector) {
        scaleOngoing = false;
    }
    public boolean onScaleBegin(ScaleGestureDetector detector) {
        scaleOngoing = true;
        return true;
    }
    public boolean onScale(ScaleGestureDetector detector) {
        // do scaling here
        return false;
    }
});

Then have your GestureDetector's listener check whether a scale gesture is occurring:

mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        if(!scaleOngoing) {
            // do scrolling here
         }
         return true;
    }
});  

Upvotes: 7

Suhail Mehta
Suhail Mehta

Reputation: 5542

private class GestureListener extends SimpleOnGestureListener {
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                float velocityY) {

                return false;
        }

        @Override
        public boolean onSingleTapUp(MotionEvent e) {

            return super.onSingleTapUp(e);

        }

        @Override
        public boolean onDoubleTap(MotionEvent e) {
            // TODO Auto-generated method stub
            return super.onDoubleTap(e);
        }

        @Override
        public boolean onDown(MotionEvent e) {
            // TODO Auto-generated method stub
            return super.onDown(e);
        }

        @Override
        public void onLongPress(MotionEvent e) {
            // TODO Auto-generated method stub
            super.onLongPress(e);
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2,
                float distanceX, float distanceY) {
            // TODO Auto-generated method stub
            return super.onScroll(e1, e2, distanceX, distanceY);
        }


    }

TRy using this

Upvotes: 0

Related Questions