Android webview:防止将触摸手势传递给父viewpager

Posted

技术标签:

【中文标题】Android webview:防止将触摸手势传递给父viewpager【英文标题】:Android webview: prevent touch gestures being passed to parent viewpager 【发布时间】:2013-11-04 02:18:21 【问题描述】:

我有一个包含许多子视图的 viewpager;每个子视图都是一个 webview。每个 webview 都有一些用户可以与之交互的 html 对象;例如,使用滑动手势的幻灯片或用户可以在 HTML 画布上移动的可拖动圆圈。

问题是当用户对这些 HTML 对象执行手势时,viewpager 会滚动到下一个视图。我希望 HTML 对象在用户与它们交互时工作(viewpager 不滚动),并且当用户在其他地方滑动时 viewpager 滚动。我该怎么做?

附:我在 HTML 幻灯片的 javascript 中使用了 event.preventDefault()event.stopPropagation(),希望 webview 不会将触摸事件传递给父 viewpager。

【问题讨论】:

你查看类似的线程***.com/questions/7774642/… 感谢@GrIsHu,但这不适用于这种情况。该答案涵盖了 HTML Web 视图大于 viewpager 的可见区域的情况。我已经有了这份工作。 您支持的最低版本的 android 是什么?您可以控制html吗?需要的话可以改吗? @Juangcg 我支持 Android 2.3 及更高版本。而且我可以更改有关 HTML 的所有内容。 @HoangHuynh 这个问题你解决了吗? 【参考方案1】:

覆盖ViewPager"canScroll" 方法,仅当视图不是WebView 的实例时才允许滚动。

示例:

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);
    


【讨论】:

问题是当用户在 HTML 幻灯片之外但在 WebView 滑动时,ViewPager 仍应滚动。【参考方案2】:

创建自己的 ViewPager 子类并覆盖 canScroll,如下所示。

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
    

您当然需要知道幻灯片放映覆盖了屏幕的哪个部分。 这个知识必须在方法isInsideSlideShow中实现。

如果您无法掌握幻灯片放映的 x/y 坐标,另一种解决方案可能是使用从视图的最边界开始的手势作为分页手势,并使用更多从内部区域开始的手势作为幻灯片放映手势。

我将这种方法用于显示地图和图表的视图寻呼机。两者都支持自己的平移。但是当用户在左边界或右边界开始手势时,整个地图或图形就会滑开:

@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;

【讨论】:

谢谢,这是我实际使用的解决方法,但我需要比这更可靠的解决方案——因为用户可以在我的 webview 中与 HTML 交互的区域可以改变(比如,用户可以在 webview 周围拖动一个 HTML 对象)。 因此您需要以某种方式获取幻灯片放映的当前坐标。我不确定,但应该可以使用 jQuery。 谢谢,这就是我正在做的事情,但我正在寻找一个本地解决方案,这与 HTML 的更改无关。 这与您对上面@Juangcg 的评论有点矛盾:引用:“我可以更改有关 HTML 的所有内容”。有点疑惑…… 对不起,误导信息。我可以更改 HTML,但(目前)它对我来说不是一个足够好的解决方案。我的 HTML 可能包含许多用户可以在 HTML 画布上移动的可拖动对象。目前,不断计算和更新这些对象的位置并将它们发送回 android 似乎不稳定且滞后。【参考方案3】:

我的想法是实现一个 Javascript 函数来决定滚动哪些部分:

function checkScroll(x, y)
    var o = document.elementFromPoint(x, y);
    result = $('div.swiper-container').find(o).length;
    MyAndroidInterface.processReturnValue(result);

然后重写这两个方法:

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) 
    @Override
public boolean onTouchEvent(MotionEvent ev) 
    switch (ev.getAction()) 
    case MotionEvent.ACTION_DOWN:
        homepage.callJavascript("checkScroll(" + Math.round(ev.getX()) + "," + Math.round(ev.getY()) + ")");
        return super.onTouchEvent(ev);
    case MotionEvent.ACTION_MOVE:
        if (homepage.scrollSlideshowLock())
            return false;

【讨论】:

您覆盖这些方法的视图是什么?你能修复代码sn-p吗?我的意思是,它缺少一些部分...... onTouch 方法实际上是在 onIntercept 中吗? 抱歉,忘了 Android :) 没问题。谢谢。

以上是关于Android webview:防止将触摸手势传递给父viewpager的主要内容,如果未能解决你的问题,请参考以下文章

Android:将手势事件传递给另一个视图

如果*** UIView 没有收到它想要处理的手势,则将手势/触摸传递给另一个 UIView?

如何在iOS中将触摸传递给手势识别器?

通过长按在 Android WebView 中启动缩放

Chrome App webview 和触摸滚动传播

需要延迟触摸 3 指滑动而不是 1 指滑动