Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stop touch event from being intercepted by ViewPager if there is touch event in webview

I have a ViewPager that is displaying pages of Fragments. Each Fragment is a WebView that is displaying an offline website. Some of these webviews have javascript swipe events in them to make them work.

I would like to implement such that if the webview has no swipe event ( within the javascript), then the touch event is passed up to the ViewPager, if not it is consumed by the webview.

I have tried overriding the ViewPagers

@Override
public boolean onInterceptTouchEvent(MotionEvent event)
{
    return (this.swipeable) ? super.onInterceptTouchEvent(event) : false;
}

However this prevented the ViewPager from being swipeable (as expected), but also stopped the swipe event reaching the webview, so I have two undesired outcomes.

Is there any way of passing the touch event to the webView first then if it is not consumed in the fragment passing it back to the ViewPager?

In case I have made a mistake in my MyViewPager I have the code:

public class MyViewPager extends ViewPager implements   GestureDetector.OnGestureListener
{
private static final String TAG = MyViewPager.class.getSimpleName();
private boolean swipeable = true;
private float lastX   = 0;
private long lastTime = 0 ;
private GestureDetector mGestureDetector;
private boolean mScrolling = false;

public MyViewPager(Context context) {
    super(context);
    mGestureDetector = new GestureDetector(context, this);
}

public MyViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
    mGestureDetector = new GestureDetector(context, this);
}

public void setSwipeable(boolean swipeable) {
    this.swipeable = swipeable;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event)
{

   /* float speed = 0;
    if(event.getAction() == MotionEvent.ACTION_MOVE)
    {
        if(lastX!=0) {
            speed = (event.getRawX()- lastX) / (System.currentTimeMillis()-lastTime);
            if(speed < 0.0 ){speed *=-1;}
            Log.e(TAG, "Move at speed ->"+speed);
            if(speed >0.5){return false;}
        }
        lastX    = event.getRawX();
        lastTime = System.currentTimeMillis();
        return true;
    }*/
  // return true;

    return (this.swipeable) ? super.onInterceptTouchEvent(event) : false;
}

@Override
public boolean onTouchEvent(MotionEvent event)
{
    Log.i(TAG, "onTouch event");
  //  mGestureDetector.onTouchEvent(event);
    return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velX, float velY) {
    Log.i(TAG, "flinging");
    return false;
}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distX, float distY)
{
    float displacement = distX;
    return false;
}

// Unused Gesture Detector functions below

@Override
public boolean onDown(MotionEvent event) {
    return false;
}

@Override
public void onLongPress(MotionEvent event) {
    // we don't want to do anything on a long press, though you should probably feed this to the page being long-pressed.
}

@Override
public void onShowPress(MotionEvent event) {
    // we don't want to show any visual feedback
}

@Override
public boolean onSingleTapUp(MotionEvent event) {
    // we don't want to snap to the next page on a tap so ignore this
    return false;
}

}

like image 714
Mark Gilchrist Avatar asked Sep 03 '15 07:09

Mark Gilchrist


People also ask

Which method you should override to control your touch action?

To make sure that each view correctly receives the touch events intended for it, override the onInterceptTouchEvent() method.

Which method you should override to control your touch action in Android?

Android supports multiple pointers, e.g. fingers which are interacting with the screen. The base class for touch support is the MotionEvent class which is passed to Views via the onTouchEvent() method. you override the onTouchEvent() method.

How do you handle touch events in a fragment?

OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if(event. getAction() == MotionEvent. ACTION_MOVE){ //do something } return true; } }); //here the rest of your code return view; MotionEvent.

In what way gestures are preferred than touch events?

 Gestures are scripted “solutions” that take advantage of these touch events.  So instead of tracking two touch points to determine if they're moving away or closer to one another in order to manipulate the size of a photo, you can just use GESTURE_ZOOM.


1 Answers

I have got now two solutions to this problem on was extending the a ViewPager class and overriding the

public boolean onInterceptTouchEvent(MotionEvent event)
{
   // code  
}

however a much better solution was to override the

protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
  return true;
}

for completeness here is the whole class

public class ZoltansViewPager extends ViewPager {

 private static final String TAG = ZoltansViewPager.class.getSimpleName();
 private boolean swipeable = true;
 private float lastX   = 0;
 private long lastTime = 0 ;
 private GestureDetector mGestureDetector;
 private boolean mScrolling = false;


 public ZoltansViewPager(Context context) {
    super(context);
 }

 public ZoltansViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
 }


 public void setSwipeable(boolean swipeable) {
    this.swipeable = swipeable;
 }

 @Override
 protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
     Log.i(TAG , " boolean checkV ->"+checkV + ", int dx-> "+dx+", int x->"+x+", int y->"+y);
     if(x <300 || x >1700 ){return true;}
     return false;
 }
}

hope it helps someone else

like image 86
Mark Gilchrist Avatar answered Sep 24 '22 09:09

Mark Gilchrist