0

I have an Android app that is a all in a Web View. I want to catch when the user swipes on the background of the app rather than a slider or button.

I tried attaching a GestureDetector to the WebView, but that catches all swipes, including those on controls in the WebView. How can I catch background swipes only?

Roland Rabien
  • 8,750
  • 7
  • 50
  • 67
  • Are you trying to swipe between multiple WebViews (similar to GMail app?) In that case, I guess ViewPager should work (http://developer.android.com/training/implementing-navigation/lateral.html). – Mikhail Naganov May 14 '15 at 01:00
  • I'm trying to implement something similar, but instead of changing the view I want to change the data the view is displaying. I want swipe left/right to be forward/back for the current row in my data set that is being displayed. Maybe I'll look how view pager is implemented. – Roland Rabien May 14 '15 at 14:36
  • OK, one more possible alternative here is handling the swipes in JS (see http://stackoverflow.com/questions/15084675/how-to-implement-swipe-gestures-for-mobile-devices), and then using injected Java objects in order to communicate to the Java side. – Mikhail Naganov May 14 '15 at 18:59

1 Answers1

0

After reading many answers, I finally came up with a simple solution.

1 - Create a simple interface for your actions:

public interface TouchListener  {
    default void onSwipeLeft() {
        Logger.d( "Swipe left");
    }
    default void onSwipeRight() {
        Logger.d( "Swipe right");
    }
}

2 - Create a simple OnTouchListener:

public class OnSwipeWebviewTouchListener implements View.OnTouchListener {
    private final GestureDetector gestureDetector;
    public OnSwipeWebviewTouchListener(Context ctx, TouchListener touchListener) {
        gestureDetector = new GestureDetector(ctx, new GestureListener(touchListener));
    }
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return gestureDetector.onTouchEvent(event);
    }
    private final class GestureListener extends GestureDetector.SimpleOnGestureListener {
        private TouchListener touchListener;
        GestureListener(TouchListener touchListener) {
            super();
            this.touchListener = touchListener;
        }
        @Override
        public boolean onDown(MotionEvent e) {
            return false;  // THIS does the trick
        }
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            boolean result = false;
            try {
                float diffY = e2.getY() - e1.getY();
                float diffX = e2.getX() - e1.getX();
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    // You can customize these settings, so 30 is an example
                    if (Math.abs(diffX) > 30 && Math.abs(velocityX) > 30) {
                        if (diffX > 0) {
                            touchListener.onSwipeRight();
                        } else {
                            touchListener.onSwipeLeft();
                        }
                        result = true;
                    }
                } else {
                    result = false;
                }
            } catch (Exception exception) {
                exception.printStackTrace();
            }
            return result;
        }
    }
}

3 - Connect them simply together:

webView.setOnTouchListener( new OnSwipeWebviewTouchListener( getActivity(), this));
tm1701
  • 7,307
  • 17
  • 79
  • 168