How can I get onclick event on webview in android?
Solution 1:
I took a look at this and I found that a WebView
doesn't seem to send click events to an OnClickListener
. If anyone out there can prove me wrong or tell me why then I'd be interested to hear it.
What I did find is that a WebView
will send touch events to an OnTouchListener
. It does have its own onTouchEvent
method but I only ever seemed to get MotionEvent.ACTION_MOVE
using that method.
So given that we can get events on a registered touch event listener, the only problem that remains is how to circumvent whatever action you want to perform for a touch when the user clicks a URL.
This can be achieved with some fancy Handler
footwork by sending a delayed message for the touch and then removing those touch messages if the touch was caused by the user clicking a URL.
Here's an example:
public class WebViewClicker extends Activity implements OnTouchListener, Handler.Callback {
private static final int CLICK_ON_WEBVIEW = 1;
private static final int CLICK_ON_URL = 2;
private final Handler handler = new Handler(this);
private WebView webView;
private WebViewClient client;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.web_view_clicker);
webView = (WebView)findViewById(R.id.web);
webView.setOnTouchListener(this);
client = new WebViewClient(){
@Override public boolean shouldOverrideUrlLoading(WebView view, String url) {
handler.sendEmptyMessage(CLICK_ON_URL);
return false;
}
};
webView.setWebViewClient(client);
webView.setVerticalScrollBarEnabled(false);
webView.loadUrl("http://www.example.com");
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (v.getId() == R.id.web && event.getAction() == MotionEvent.ACTION_DOWN){
handler.sendEmptyMessageDelayed(CLICK_ON_WEBVIEW, 500);
}
return false;
}
@Override
public boolean handleMessage(Message msg) {
if (msg.what == CLICK_ON_URL){
handler.removeMessages(CLICK_ON_WEBVIEW);
return true;
}
if (msg.what == CLICK_ON_WEBVIEW){
Toast.makeText(this, "WebView clicked", Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
}
Solution 2:
You can implement an OnClickListener via OnTouchListener:
webView.setOnTouchListener(new View.OnTouchListener() {
public final static int FINGER_RELEASED = 0;
public final static int FINGER_TOUCHED = 1;
public final static int FINGER_DRAGGING = 2;
public final static int FINGER_UNDEFINED = 3;
private int fingerState = FINGER_RELEASED;
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
if (fingerState == FINGER_RELEASED) fingerState = FINGER_TOUCHED;
else fingerState = FINGER_UNDEFINED;
break;
case MotionEvent.ACTION_UP:
if(fingerState != FINGER_DRAGGING) {
fingerState = FINGER_RELEASED;
// Your onClick codes
}
else if (fingerState == FINGER_DRAGGING) fingerState = FINGER_RELEASED;
else fingerState = FINGER_UNDEFINED;
break;
case MotionEvent.ACTION_MOVE:
if (fingerState == FINGER_TOUCHED || fingerState == FINGER_DRAGGING) fingerState = FINGER_DRAGGING;
else fingerState = FINGER_UNDEFINED;
break;
default:
fingerState = FINGER_UNDEFINED;
}
return false;
}
});
Solution 3:
Hamidreza's solution almost worked for me.
I noticed from experimentation that a simple tap usually has 2-5 action move events. Checking the time between action down and up was simpler and behaved more like what I expected.
private class CheckForClickTouchLister implements View.OnTouchListener {
private final static long MAX_TOUCH_DURATION = 100;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
m_DownTime = event.getEventTime(); //init time
break;
case MotionEvent.ACTION_UP:
if(event.getEventTime() - m_DownTime <= MAX_TOUCH_DURATION)
//On click action
break;
default:
break; //No-Op
}
return false;
}