3

Does anyone know how to combine onLongPress(MotionEvent e) and onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)? Idea is to start with onLongPress but continue with sliding across some view.

Current code i have:

private class CustomListener implements View.OnTouchListener {

    ImagePreviewer imagePreviewer = new ImagePreviewer();

    private GestureDetector gestureDetector = new GestureDetector(getActivity(), new GestureDetector.SimpleOnGestureListener() {

        ImageView currentImageView;

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {

            float x = e2.getX();
            float y = e2.getY() + mConstraintLayoutContainerCoordinates[1];

            currentImageView = getProperImage(mCurrentImagesNumberForPoll, (int) x, (int) y);

            if(currentImageView != null) {
                imagePreviewer.show(getActivity(), currentImageView);
            }

            return super.onScroll(e1, e2, distanceX, distanceY);
        }

        @Override
        public void onLongPress(MotionEvent e) {

            Log.d(TAG, "LONG PRESS");

            float x = e.getX();
            float y = e.getY() + mConstraintLayoutContainerCoordinates[1];
            currentImageView = getProperImage(mCurrentImagesNumberForPoll, (int) x, (int) y);
            if(currentImageView != null) {
                imagePreviewer.show(getActivity(), currentImageView);
            }

            super.onLongPress(e);
        }
    });

    @Override
    public boolean onTouch(View v, MotionEvent event) {

        if(event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
            Log.d("TAG", "DOWN  or CANCEL ");
            imagePreviewer.hide();
        }
        gestureDetector.onTouchEvent(event);
        return true;
    }
}

Thing is that either onScroll() is called (when i slide finger across the view) or onLongPress(), but i want to start with onLongPress(), then detect sliding so i can choose proper view to show accordingly.

RadoVidjen
  • 432
  • 7
  • 17

3 Answers3

3

GestureDetectorCompat blocks calls to onScroll after a onLongPress has been detected. The block can be canceled by sending ACTION_CANCEL to the detector.

@Override
public void onLongPress(MotionEvent e) {
    isLongPressed = true;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (detector.onTouchEvent(event)) {
        return true;
    }

    switch (event.getActionMasked()) {
        case MotionEvent.ACTION_MOVE:
            if (isLongPressed) {
                isLongPressed = false;
                MotionEvent cancel = MotionEvent.obtain(event);
                cancel.setAction(MotionEvent.ACTION_CANCEL);
                detector.onTouchEvent(cancel);
            }
            break;
    }
    return super.onTouchEvent(event);
}
jayeffkay
  • 1,229
  • 1
  • 16
  • 22
  • Thanks - this worked like a charm! This allows a long press to be detected, while at the same time allowing it to continue into a movement gesture. Spot on! – Taqras Feb 06 '23 at 08:35
1

GestureDetector.setIsLongpressEnabled(false): https://developer.android.com/reference/android/view/GestureDetector.html#setIsLongpressEnabled(boolean) but in this way you loose the onLongClick event. However you could implement your onLongClick event by counting how much time is passed from the initial "down" touch and then raise your Code/Listener after that amount of time.

emandt
  • 2,547
  • 2
  • 16
  • 20
0

I have implemented the above feature little differently.I use onLongPress(MotionEvent e) to get if long press is triggered and create a flag that mLongClicked=true and once that is done i do scrolling on my own in onTouch() as once longPress is called onScroll is not called by framework. This is just a work around and work's perfectly.

override fun onTouchEvent(event: MotionEvent?): Boolean {
        gestureDetector.onTouchEvent(event)    

        when (event.action) {
            MotionEvent.ACTION_MOVE -> {
                if (dragEvent) {
                    //Add on Move logic here for scroll
                    scrollListener.onDragEvent(DragEventType.move, event.x, event.y)
                    return false
                }
                if (mLongClicked) {
                    mLongClicked = false
                    dragEvent = true
                }
            }
            MotionEvent.ACTION_UP -> {
                if (dragEvent) {
                    //Add on Up logic here for scroll
                    scrollListener.onDragEvent(DragEventType.up, event.x, event.y)
                    dragEvent = false
                }
            }
        }
        return true
    }

And onLongPress() will look like this:

override fun onLongPress(event: MotionEvent) {
            mLongClicked = true
            //Add on Down logic here for scroll
            zoomViewListener.onDragEvent(DragEventType.down, event.x, event.y)
        }

NOTE: I am using a listener to scroll even't outside view and manipulate, you can do here itself.And if you are thinking about down event than it is taken care by onLongPress()

I prefer Kotlin over java :p

Anmol
  • 8,110
  • 9
  • 38
  • 63