Android onTouchEvent and JavaScript onclick events
[Revised]
I did manage to get this to work, but I'm not sure this is the correct way to do it. Comments are welcome.
In the onTouchEvent
in the WebView, I pass the event up to super
and return true
(which prevents the event from propagating further and allows JavaScript to do its thing). But before returning, I also direct the event to the parent container's onTouchEvent
-- but I have to cast the container to a class that has onTouchEvent
or specify an interface. In my case, the WebView's onTouchEvent
now looks like this:
@Override
public boolean onTouchEvent(MotionEvent ev) {
super.onTouchEvent(ev);
((RelativeLayout)getParent()).onTouchEvent(ev);
return true;
}
It works, but is this a proper solution?
I cannot figure out how to have an Android Webview 'share' touch events with both the HTML page (via JavaScript) and the rest of the application. From what I'm seeing, it looks like either JavaScript can see the touches or the WebView's parents can, but not both. Does anyone know a work-around?
Below is a working example with an Activity (TestActivity.java), a RelativeLayout (TestLayout.java) and a WebView (TestWebView.java). The WebView has an onTouchEvent
(which declares whether the touch event has been handled) and a simple HTML page. There are three places where touch events are detected:
- the HTML page (via an
onclick
around an<h1>
-- if you touch it, the page turns color; - the onTouchEvent of the WebView -- if you touch it, a message is logged;
- the onTouchEvent of the Layout -- if you touch it, another message is logged.
If the WebView's onTouch
returns true
(signaling that it's "handled" the event), the JS onclick
works (the page changes colour) but the parent's onTouchEvent
is never reached (which you would expect). If the WebView's onTouchEvent
returns 'false', the parent's onTouchEvent
is invoked, but the JS never receives the event (strangely a box appears around the word to show that it's been touched, but the JS never executes).
TestActivity.java
package com.scriptfoundry.LinkTest;
import android.app.Activity;
import android.os.Bundle;
public class LinkTestActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TestLayout layout = new TestLayout(this);
TestWebView webView = new TestWebView(this);
layout.addView(webView);
setContentView(layout);
}
}
TestLayout.java:
package com.scriptfoundry.LinkTest;
import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.RelativeLayout;
public class TestLayout extends开发者_开发百科 RelativeLayout {
public TestLayout(Context context) {
super(context);
setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
setBackgroundColor(Color.LTGRAY);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
Log.d("Info","TestLayout onTouchEvent invoked");
return false;
}
}
TestWebView.java:
package com.scriptfoundry.LinkTest;
import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.util.Xml.Encoding;
import android.view.MotionEvent;
import android.webkit.WebView;
import android.widget.RelativeLayout;
public class TestWebView extends WebView {
public TestWebView(Context context) {
super(context);
setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT,RelativeLayout.LayoutParams.FILL_PARENT));
setBackgroundColor(Color.WHITE);
getSettings().setJavaScriptEnabled(true);
loadData("<html><head></head><body><h1 onclick=\"document.body.style.backgroundColor=document.body.style.backgroundColor==='red'?'blue':'red'\">Change colour</h1><body></html>","text/html",Encoding.UTF_8.toString());
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
Log.d("Info","TestWebView onTouchEvent invoked");
super.onTouchEvent(ev);
return false;
}
}
精彩评论