Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android webview: prevent touch gestures being passed to parent viewpager

I have a viewpager that contains many child views; each child view is a webview. Each webview has some HTML objects that user can interact with; for instance, a slideshow that works on swipe gestures or a draggable circle that user can move around the HTML canvas.

The problem is when user performs a gesture on these HTML objects, the viewpager scrolls to next view. I want the HTML objects to work when user interacts with them (viewpager doesn't scroll), and the viewpager to scroll when user swipes elsewhere. How can I do that?

Webviews inside Viewpager

P.S. I have used event.preventDefault() and event.stopPropagation() in the JavaScript of the HTML slideshow with hope that the webview would not pass touch events to parent viewpager.

like image 360
Hoang Huynh Avatar asked Oct 25 '13 05:10

Hoang Huynh


2 Answers

Override the "canScroll" method of your ViewPager and allow scrolling only if the view is not a instance of WebView.

Sample:

public class MyViewPager extends ViewPager {

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

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

    @Override
    protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
        if(v instanceof WebView){
            return true;
        }
        return super.canScroll(v, checkV, dx, x, y);
    }

}
like image 52
Mohan Krishna Avatar answered Nov 19 '22 14:11

Mohan Krishna


Create your own subclass of ViewPager and overwrite canScroll as follows.

class MyViewPager extends ViewPager {
...

@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
    if (isInsideSlideShow(x,y)) {
        return true; // allow the slide show its own scrolling
    } else {
        return false; // ViewPager scrolls
    }
}

You will somehow of course need to know, which part of the screen is covered by the slide show. This knowledge must be implemented in the method isInsideSlideShow.

If you can't get hold of the x/y coordinates of the slide show, another solution could be to use gestures starting at the very border of the view as paging gestures and gestures starting more in the inner area as slide show gestures.

I am using this approach for a view pager which shows a map and a graph. Both are supporting their own panning. But when the user starts the gesture at the left or right border, the whole map or graph is slid away:

@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
        int width = getWidth();
        int slideWidth = Math.round(width * 0.15f);
        if (x < slideWidth || x > width - slideWidth) {
            return false;
        }
        return true;
}
like image 3
user2808624 Avatar answered Nov 19 '22 15:11

user2808624