检查Android WebView是否正在消耗触摸事件

简洁版本

如何检测Android WebView是否消耗触摸事件? onTouchEvent总是返回true,并且从不触发WebViewClientonUnhandledInputEvent

详细版本

我有一个TwoDScrollView内的多个WebViews。 顾名思义,TwoDScrollView既可以垂直滚动也可以水平滚动。 TwoDScrollView的内容可以放大/缩小。 当用户拖动他的手指或使用捏缩放,我想分配触摸事件:

  • WebView如果其内容是可滚动/可缩放的(即只有WebView的内部将滚动/缩放)
  • TwoDScrollView如果上述条件为false(TwoDScrollView的所有内容将滚动/缩放)

我已经通过使用canScrollHorizontallycanScrollVertically方法部分实现了这一点。 但是这些方法只适用于“本地滚动”。 但是,在某些情况下,WebView中的一些JavaScript会消耗触摸事件,例如Google地图。 在这种情况下,这些方法返回false。 有什么方法可以查明WebView的内容是否消耗触摸事件,即可滚动/可缩放吗? 我无法更改WebView的内容,因此我的问题与此不同。

我已经考虑通过evaluateJavaScript方法在Webview中执行一些JavaScript来检查触摸处理程序,但根据这个答案 ,没有简单的方法来实现这一点,也可以有一些其他嵌套的iframe。 任何帮助将不胜感激。

我已经试过了

  1. onTouchEvent了WebView的onTouchEvent并且读取了总是返回true的super.onTouchEvent() ,不pipe怎样。
  2. 如上所述, canScrollHorizontallycanScrollVertically只能部分地解决这个问题
  3. onScrollChanged也没有用
  4. WebViewClient.onUnhandledInputEvent从不被触发
  5. 我考虑通过evaluateJavaScript使用JavaScript,但这是一个非常复杂和难看的解决scheme
  6. 我试图通过Debug.startMethodTracing来跟踪Debug.startMethodTracing 。 我发现它传播如下:
    • android.webkit.WebView.onTouchEvent
    • com.android.webview.chromium.WebViewChromium.onTouchEvent
    • com.android.org.chromium.android_webview.AwContents.onTouchEvent
    • com.android.org.chromium.android_webview.AwContents$AwViewMethodsImpl.onTouchEvent
    • com.android.org.chromium.content.browser.ContentViewCore.onTouchEventImpl
    • 根据ContentViewCore的源代码 ,触摸事件以nativeOnTouchEvent本地方法nativeOnTouchEvent ,我不知道会发生什么。 无论如何, onTouchEvent总是返回true,即使有可能find事件是否被消耗,也需要使用私有方法,这也是相当丑陋的。

注意

我不需要知道如何拦截发送给WebView的触摸事件,但WebView是否正在使用它们,即正在使用它们做任何事情,例如滚动,拖动等。

根据这个问题报告 ,不可能的。 如果网页代码在你的控制之下,你可以实现一些JavaScriptInterface来解决这个问题。 如果没有,恐怕这里没有办法解决。

您可以通过覆盖WebView GestureDetector来将所有touch事件传递给GestureDetector ,以便您可以随时通过侦听GestureDetector来知道Android WebView何时任何地方消费触摸事件

尝试像这样:

 public class MyWebView extends WebView { private Context context; private GestureDetector gestDetector; public MyWebView(Context context) { super(context); this.context = context; gestDetector = new GestureDetector(context, gestListener); } @Override public boolean onTouchEvent(MotionEvent event) { return gd.onTouchEvent(event); } GestureDetector.SimpleOnGestureListener gestListener= new GestureDetector.SimpleOnGestureListener() { public boolean onDown(MotionEvent event) { return true; } public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) { //if (event1.getRawX() > event2.getRawX()) { // show_toast("swipe left"); //} else { // show_toast("swipe right"); //} //you can trace any touch events here return true; } }; void show_toast(final String text) { Toast t = Toast.makeText(context, text, Toast.LENGTH_SHORT); t.show(); } } 

我希望你受到启发。

这段代码将在webview中处理你的滚动事件。 这捕获点击和点击事件,并比较每个的位置。 它不介意webview内的内容是可滚动的,只是比较webview区域的坐标。

 public class MainActivity extends Activity implements View.OnTouchListener, Handler.Callback { private float x1,x2,y1,y2; //x1, y1 is the start of the event, x2, y2 is the end. static final int MIN_DISTANCE = 150; //min distance for a scroll event private static final int CLICK_ON_WEBVIEW = 1; private static final int CLICK_ON_URL = 2; private static final int UP_ON_WEBVIEW = 3; private final Handler handler = new Handler(this); public WebView webView; private WebViewClient client; private WebAppInterface webAppInt = new WebAppInterface(this); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webView = (WebView)findViewById(R.id.myWebView); webView.setOnTouchListener(this); client = new WebViewClient(); webView.setWebViewClient(client); webView.loadDataWithBaseURL("file:///android_asset/", "myweb.html", "text/html", "UTF-8", ""); } //HERE START THE IMPORTANT PART @Override public boolean onTouch(View v, MotionEvent event) { if (v.getId() == R.id.myWebView && event.getAction() == MotionEvent.ACTION_DOWN){ x1 = event.getX(); y1 = event.getY(); handler.sendEmptyMessageDelayed(CLICK_ON_WEBVIEW, 200); } else if (v.getId() == R.id.myWebView && event.getAction() == MotionEvent.ACTION_UP){ x2 = event.getX(); y2 = event.getY(); handler.sendEmptyMessageDelayed(UP_ON_WEBVIEW, 200); } return false; } @Override public boolean handleMessage(Message msg) { if (msg.what == CLICK_ON_URL){ //if you clic a link in the webview, thats not a scroll handler.removeMessages(CLICK_ON_WEBVIEW); handler.removeMessages(UP_ON_WEBVIEW); return true; } if (msg.what == CLICK_ON_WEBVIEW){ //Handle the click in the webview Toast.makeText(this, "WebView clicked", Toast.LENGTH_SHORT).show(); return true; } if (msg.what == UP_ON_WEBVIEW){ float deltaX = x2 - x1; //horizontal move distance float deltaY = y2 - y1; //vertical move distance if ((Math.abs(deltaX) > MIN_DISTANCE) && (Math.abs(deltaX) > Math.abs(deltaY))) { // Left to Right swipe action if (x2 > x1) { //Handle the left to right swipe Toast.makeText(this, "Left to Right swipe", Toast.LENGTH_SHORT).show (); } // Right to left swipe action else { //Handle the right to left swipe Toast.makeText(this, "Right to Left swipe", Toast.LENGTH_SHORT).show (); } } else if ((Math.abs(deltaY) > MIN_DISTANCE) && (Math.abs(deltaY) > Math.abs(deltaX))) { // Top to Bottom swipe action if (y2 > y1) { //Handle the top to bottom swipe Toast.makeText(this, "Top to Bottom swipe", Toast.LENGTH_SHORT).show (); } // Bottom to top swipe action -- I HIDE MY ACTIONBAR ON SCROLLUP else { getActionBar().hide(); Toast.makeText(this, "Bottom to Top swipe [Hide Bar]", Toast.LENGTH_SHORT).show (); } } return true; } return false; } } 

您也可以尝试控制滑动的速度,将其检测为真正的滑动或滚动。

我希望能帮到你。

尝试在XML中设置android:isClickable="true" ,并在Java代码中创build一个onClickListener