检查Android WebView是否正在消耗触摸事件
简洁版本
如何检测Android WebView是否消耗触摸事件? onTouchEvent
总是返回true,并且从不触发WebViewClient
的onUnhandledInputEvent
。
详细版本
我有一个TwoDScrollView内的多个WebViews。 顾名思义,TwoDScrollView既可以垂直滚动也可以水平滚动。 TwoDScrollView的内容可以放大/缩小。 当用户拖动他的手指或使用捏缩放,我想分配触摸事件:
- WebView如果其内容是可滚动/可缩放的(即只有WebView的内部将滚动/缩放)
- TwoDScrollView如果上述条件为false(TwoDScrollView的所有内容将滚动/缩放)
我已经通过使用canScrollHorizontally
和canScrollVertically
方法部分实现了这一点。 但是这些方法只适用于“本地滚动”。 但是,在某些情况下,WebView中的一些JavaScript会消耗触摸事件,例如Google地图。 在这种情况下,这些方法返回false。 有什么方法可以查明WebView的内容是否消耗触摸事件,即可滚动/可缩放吗? 我无法更改WebView的内容,因此我的问题与此不同。
我已经考虑通过evaluateJavaScript
方法在Webview中执行一些JavaScript来检查触摸处理程序,但根据这个答案 ,没有简单的方法来实现这一点,也可以有一些其他嵌套的iframe。 任何帮助将不胜感激。
我已经试过了
- 我
onTouchEvent
了WebView的onTouchEvent
并且读取了总是返回true的super.onTouchEvent()
,不pipe怎样。 - 如上所述,
canScrollHorizontally
和canScrollVertically
只能部分地解决这个问题 -
onScrollChanged
也没有用 -
WebViewClient.onUnhandledInputEvent
从不被触发 - 我考虑通过
evaluateJavaScript
使用JavaScript,但这是一个非常复杂和难看的解决scheme - 我试图通过
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
。