Retrieve Element Intended for Click, But Click Event Canceled by Java Code in WebView
Nitish Kumar Singh
Dec 5, 2023Hello developers! In this blog post, we will learn how to "Retrieve the Element Intended for a Click, but the Click Event is Canceled by Java Code in WebView." Okay, let's simplify it. I want to retrieve an element (JavaScript object of an HTML element) in JavaScript code that is about to be clicked, but it was not clicked because I canceled the click event in Java code within the onTouch method of OnTouchListener attached to the WebView.
Okay, maybe you're wondering, "Why do I want to do this?" or maybe not if you're searching for this. Just watch the video below, and you'll automatically understand why I want to do this.
To achieve this, we use OnTouchListener
on the WebView
to cancel the click event, the loadUrl()
method of WebView to run JS code, and the elementFromPoint()
function of the document
(DOM document) to get the element that is about to be clicked.
The following is the Java code to perform all these tasks:
WebView webView = findViewById(R.id.yourWebViewId);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient());
// if you want to get some data from JS code
webView.addJavascriptInterface(new JsBridge(){
@Override
public void takeDataFromJS (String data) {
// Do what you want with data
}
},"AndroidJsBridge");
// load url you want
webView.loadUrl("https://example.com/");
// To cancel click event and get click points and run desire JS code
webView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// Get the x and y coordinates of the touch event
int x = (int) event.getX();
int y = (int) event.getY();
Log.d(TAG, "onTouch: ");
// Execute JavaScript to find the element under the touch coordinates
webView.loadUrl("javascript:((x,y)=>{\n" +
"var r = document.elementFromPoint(x,y);\n" +
// Do wat you want to do with this element and then finally pass data as string to Java code
"window.AndroidJsBridge.takeDataFromJS(JSON.stringify(data));"+
"})("+x/screenDensityOfPhone+","+y/screenDensityOfPhone+");");
}
}
});
In the above code, screenDensityOfPhone
is a variable of type float
, and we can get it using the code below:
float screenDensityOfPhone = getResources().getDisplayMetrics().density;
We use screenDensityOfPhone
because Java pixels and JS pixels are not the same. The JsBridge
class is defined as follows:
public class JsBridge {
@JavascriptInterface
public void takeDataFromJS(String data){
}
}
The elementFromPoint()
function of the document
returns the topmost element at the specified coordinates (relative to the viewport). You can also use the elementsFromPoint
function to get all elements at the specified coordinates that are available one over the other.
Okay, I hope you learn how to do this and gain something by reading this blog post.