如何检测Android WebView是否消耗了触摸事件? onTouchEvent
始终返回true,WebViewClient
onUnhandledInputEvent
永远不会被触发。
我在TwoDScrollView中有多个WebView。顾名思义,TwoDScrollView可以垂直和水平滚动。 TwoDScrollView的内容可以放大/缩小。当用户拖动手指或使用双指缩放时,我想将触摸事件发送到:
我已使用canScrollHorizontally
和canScrollVertically
方法部分实现了这一目标。但是这些方法仅适用于原生滚动"。但是,在某些情况下,WebView中的某些JavaScript会消耗触摸事件,例如Google Maps。在这种情况下,方法返回false。有没有办法找出WebView的内容是否消耗触摸事件,即可滚动/可缩放?我无法更改WebView的内容,因此我的问题与this one不同。
我已经考虑通过evaluateJavaScript
方法在Webview中执行一些JavaScript来检查触摸处理程序,但是根据this answer,没有简单的方法来实现这一点,而且页面也可以有其他一些嵌套I帧。任何帮助将不胜感激。
onTouchEvent
并阅读super.onTouchEvent()
,无论如何,它总是返回true。canScrollHorizontally
和canScrollVertically
仅部分解决了此问题,如上所述onScrollChanged
不是很有用WebViewClient.onUnhandledInputEvent
永远不会被触发evaluateJavaScript
使用JavaScript,但这是一个非常复杂和丑陋的解决方案Debug.startMethodTracing
跟踪MotionEvent。我发现它传播如下:
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
nativeOnTouchEvent
结束,我不知道它会发生什么。无论如何,onTouchEvent
总是返回true,即使有可能在某处发现事件是否被消耗,也需要使用非常丑陋的私有方法。我不需要知道如何拦截发送到WebView的触摸事件,但是WebView是否正在使用它们,即是否正在使用它们执行任何操作,例如滚动,拖动等。
答案 0 :(得分:1)
根据这个issue report,不可能。 如果Web代码在您的控制之下,您可以实现一些JavaScriptInterface来解决此问题。如果没有,我担心这里没有解决方案。
答案 1 :(得分:0)
您可以通过覆盖touch
的{{1}}将所有GestureDetector
个事件传递给onTouchEvent
,这样您就可以知道当Android WebView随时随地都在使用触摸事件时听取WebView
。
试试这样:
GestureDetector
我希望你受到启发。
答案 2 :(得分:-1)
此代码将处理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;
}
}
您还可以尝试控制滑动的速度,将其检测为真正的滑动或滚动。
我希望能帮助你。
答案 3 :(得分:-1)
实际上现在 webview 不支持触摸操作。但是有一些解决方法可用; 我将用一个长按示例来展示它:我使用 Pointoption 因为我将获得元素的坐标并将其用于长按。
public void longpress(PointOption po) {
//first you need to switch to native view
driver.switchToNativeView();
TouchAction action = new TouchAction((PerformsTouchActions) driver);
action.longPress(po).waitAction(WaitOptions.waitOptions(Duration.ofSeconds(2)));
action.release();
action.perform();
driver.switchToDefaultWebView();
}
为了得到我在methood下面设计的元素的坐标
public PointOption getElementLocation(WebElement element) {
int elementLocationX;
int elementLocationY;
//get element location in webview
elementLocationX = element.getLocation().getX();
elementLocationY = element.getLocation().getY();
//get the center location of the element
int elementWidthCenter = element.getSize().getWidth() / 2;
int elementHeightCenter = element.getSize().getHeight() / 2;
int elementWidthCenterLocation = elementWidthCenter + elementLocationX;
int elementHeightCenterLocation = elementHeightCenter + elementLocationY;
//calculate the ratio between actual screen dimensions and webview dimensions
float ratioWidth = device.getDeviceScreenWidth() / ((MobileDevice) device)
.getWebViewWidth().intValue();
float ratioHeight = device.getDeviceScreenHeight() / ((MobileDevice) device)
.getWebViewHeight().intValue();
//calculate the actual element location on the screen , if needed you can increase this value,for example i used 115 for one of my mobile devices.
int offset = 0;
float elementCenterActualX = elementWidthCenterLocation * ratioWidth;
float elementCenterActualY = (elementHeightCenterLocation * ratioHeight) + offset;
float[] elementLocation = {elementCenterActualX, elementCenterActualY};
int elementCoordinateX, elementCoordinateY;
elementCoordinateX = (int) Math.round(elementCenterActualX);
elementCoordinateY = (int) Math.round(elementCenterActualY);
PointOption po = PointOption.point(elementCoordinateX, elementCoordinateY);
return po;
}
现在你有一个 longpress(PointOption po) 和 getElementLocation(Webelement element) 方法来给你 po。现在一切准备就绪,您可以按如下方式使用它们..
longpress(getElementLocation(driver.findElement(By.id("the selector can be any of them(xpath,css,classname,id etc.)")));
答案 4 :(得分:-2)
尝试在XML中设置android:isClickable="true"
并在Java代码中创建onClickListener
。