Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting View's touch location to WebView's HTML screen location

I have a WebView that is displaying a local HTML page within the assets folder. The WebView is part of larger layout in an Activity. I'm trying to allow users to drag text from an EditText widget to an Input Element within the WebView. Everything works good except for converting the screen coordinates received by the drag listener to the screen coordinates used by document.elementFromPoint. They don't match up. It'll keep dropping text into input boxes which are further down then the users finger. Any help would be appreciated. Warning: my javascript knowledge is pretty pathetic.

Basic flow:

  1. WebView's onDrag event catches the ACTION_DROP event.
  2. The event's x, y location is passed to a Javascript function
  3. The Javascript function finds element based on points and updates the value

In my 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 wrapper:

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

Javascript function:

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

    if (elem.tagName == "INPUT") {
        elem.value = text;
    }
}
</script>
like image 747
Jay Soyer Avatar asked Nov 08 '12 19:11

Jay Soyer


1 Answers

Figured it out. Was making the conversion more complicated then what it needed to be. Both Android's WebView and the WebPage have their own coordinate system based on the size of their visible view port. Yes both report different sized view ports. Even though both view ports can be scrolled, there's no need to include those scrolled changes. The simple formula:

DE = DragEvent
WV = WebView

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

How my code looks now:

In 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 wrapper:

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

Javascript function:

<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>
like image 88
Jay Soyer Avatar answered Nov 04 '22 05:11

Jay Soyer