将视图的触摸位置转换为WebView的HTML屏幕位置

6
我有一个WebView,它显示了位于assets文件夹中的本地HTML页面。这个WebViewActivity中更大布局的一部分。我试图允许用户将EditText小部件中的文本拖动到WebView中的输入元素中。除了将拖动监听器接收到的屏幕坐标转换为document.elementFromPoint使用的屏幕坐标之外,一切都很好。它们不匹配。它会将文本放入比用户手指更远的输入框中。任何帮助都将不胜感激。警告:我的JavaScript知识非常差。

基本流程:

  1. WebView的onDrag事件捕获ACTION_DROP事件。
  2. 将事件的x、y位置传递给JavaScript函数
  3. JavaScript函数根据点找到元素并更新值

在我的Activity中:

private class OnWebViewDragListener implements OnDragListener {
    public boolean onDrag(View v, DragEvent event) {
        switch (event.getAction()) {
            case DragEvent.ACTION_DROP:
                String dropText = event.getClipData().getItemAt(0).getText().toString();
                mJavaScript._dropText(mWebView, dropText, event.getX(), event.getY());
                return true;

            default:
                break;
        }

        return false;
    }
}

Javascript包装器:

public void _dropText(WebView wv, String text, float x, float y) {
    wv.loadUrl("javascript:dropText('" + text + "', " + x + ", " + y + ")");
}

Javascript函数:

<script type="text/javascript">
function dropText(text, x, y) {
    var elem = document.elementFromPoint(x, y);

    if (elem.tagName == "INPUT") {
        elem.value = text;
    }
}
</script>
1个回答

10

搞定了。我把转换过程弄得比必要的要复杂。Android的WebView和WebPage都有自己的坐标系,基于它们可见视口的大小。是的,两个视口都会报告不同大小。即使两个视口都可以滚动,也没有必要包括这些滚动变化。简单的公式:

DE = DragEvent
WV = WebView

x = DE.getX() * (window.innerWidth / WV.getWidth());
y = DE.getY() * (window.innerHeight / WV.getHeight());

现在我的代码看起来是这样的:

在Activity中:

private class OnWebViewDragListener implements OnDragListener {
    public boolean onDrag(View v, DragEvent event) {
        switch (event.getAction()) {
            case DragEvent.ACTION_DROP:
                String dropText = event.getClipData().getItemAt(0).getText().toString();
                mJavaScript._dropText(mWebView, dropText, event.getX(), event.getY());
                return true;

            default:
                break;
        }

        return false;
    }
}

Javascript包装器:

public void _dropText(WebView wv, String text, float x, float y) {
    wv.loadUrl("javascript:dropText('" + text + "', " + x + ", " + y + ", " + wv.getHeight()
            + ", " + wv.getWidth() + ")");
}

Javascript函数:

<script type="text/javascript">
function dropText(text, x, y, height, width) {
    x *= (window.innerWidth / width);
    y *= (window.innerHeight / height);

    var elem = document.elementFromPoint(x, y);

    if (elem.tagName == "INPUT") {
        elem.value = text;
    }
}
</script>

嗨@Jay,感谢您提供这个很棒的解决方案。我花了几个小时摆弄来找出最好的方式来翻译坐标:) 顺便问一下,当您拖动对象时是否遇到了一些问题?例如,我一直收到“正在进行拖动,但没有拖动窗口句柄”,因此我的on touch move事件停止触发。这是我的代码:https://gist.github.com/anonymous/8161cae250a9f0c9002a - ShP
这听起来有点熟悉,但我无法完全回忆起来。已经过去3年了,我不再能够访问这段代码。 - Ifrit
也对我很好用。谢谢! - Shilpi
现在,它相当于 cssX = viewX / window.devicePixelRatio; cssY = viewY / window.devicePixelRatio。这假设 HTML 视口填充了整个 Webview。 - hldev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接