Android Question WebView: how to disable dragging of links?

Sandman

Expert
Licensed User
Longtime User
I have a webview with text, links and other webpage things. If I press and hold on a link for a second, a gray rectangle show the name of the link and the url, which then can be dragged to some other place on the screen.

Does anyone know if this can be disabled? Please note that I still need the link to be clickable.

(Why? Because the link only contains internal data that I catch in the click event and then do app-things using them. It just looks weird for the user to see that link.)
 
Solution
ChatGPT suggests this code in the Page_Finished event to prevent dragging:
B4X:
Dim wve as WebViewExtras
Dim wv as webview

Sub wv_PageFinished (Url As String)

    ' JavaScript to disable drag for links
    Dim js As String
    js = "var links = document.getElementsByTagName('a');" &
         "for(var i = 0; i < links.length; i++) {" &
         "  links[i].addEventListener('dragstart', function(event) {" &
         "    event.preventDefault();" &
         "  }, false);" &
         "}"
     wve.executeJavascript(wv, js)

End Sub

If you want to prevent even the hilight when tap+hold, then ChatGPT has code for that too - just let me know if you want me to post that also.

JohnC

Expert
Licensed User
Longtime User
ChatGPT suggests this code in the Page_Finished event to prevent dragging:
B4X:
Dim wve as WebViewExtras
Dim wv as webview

Sub wv_PageFinished (Url As String)

    ' JavaScript to disable drag for links
    Dim js As String
    js = "var links = document.getElementsByTagName('a');" &
         "for(var i = 0; i < links.length; i++) {" &
         "  links[i].addEventListener('dragstart', function(event) {" &
         "    event.preventDefault();" &
         "  }, false);" &
         "}"
     wve.executeJavascript(wv, js)

End Sub

If you want to prevent even the hilight when tap+hold, then ChatGPT has code for that too - just let me know if you want me to post that also.
 
Last edited:
Upvote 0
Solution

drgottjr

Expert
Licensed User
Longtime User
elements are only draggable if you declare them as such. i'm guessing you didn't make them draggable, so what you are seeing is the default action when somebody tries to drag a non-draggable element. you need to kill what you refer to as the gray rectangle (aka, "the gray matter"). our resident chatgpt maven @JohnC has become quite adept at managing that frightening entity, so i'll leave it to him to do his thing. go, @JohnC!
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
To remove the hilight square, ChatGPT responded with this:

To prevent a link from being highlighted and showing its URL when a user taps and holds on it in a WebView in your B4A project, you can utilize CSS and JavaScript. The goal here is to suppress the default context menu that appears when long-pressing a link, which is typically the behavior that reveals the URL. Additionally, using CSS, you can prevent the visual highlighting of the link during a tap hold.

Since B4A's WebView works with standard web technologies, you can inject CSS and JavaScript into your WebView content to achieve this. Here's how you can modify the previous example to include these behaviors:


  1. CSS to Prevent Link Highlighting: You'll inject CSS to remove any visual cues that a link is being interacted with, such as color changes or underlines that might appear on a long press.
  2. JavaScript to Prevent the Context Menu: You'll use JavaScript to suppress the default context menu for links.
Here's an updated version of the B4A code incorporating these changes:
B4X:
Sub Globals
    'These global variables will be redeclared each time the activity is created.
    Dim WebView1 As WebView
    Dim WVE As WebViewExtras
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Initialize the WebView and WebViewExtras
    WebView1.Initialize("WebView1")
    WVE.Initialize(WebView1)
    Activity.AddView(WebView1, 0, 0, 100%x, 100%y)

    'Enable JavaScript
    WVE.addJavascriptInterface(WebView1, "B4A")
   
    'Load the URL
    WebView1.LoadUrl("https://yourwebsite.com")
End Sub

Sub WebView1_PageFinished (Url As String)
    ' CSS to prevent highlighting of links on tap hold
    Dim css As String
    css = "a, a:active, a:focus { outline: none !important; -webkit-tap-highlight-color: rgba(0,0,0,0); }"

    ' JavaScript to prevent the default context menu (long press menu)
    Dim js As String
    js = "javascript:(function() {" & _
         "document.body.style.webkitTouchCallout='none';" & _ ' Prevents the callout on long press
         "document.body.style.webkitUserSelect='none';" & _ ' Prevents text selection
         "var style = document.createElement('style');" & _
         "style.type = 'text/css';" & _
         "style.appendChild(document.createTextNode('" & css & "'));" & _
         "document.head.appendChild(style);" & _
         "var links = document.getElementsByTagName('a');" & _
         "for(var i = 0; i < links.length; i++) {" & _
         "  links[i].addEventListener('touchstart', function(e) { e.preventDefault(); }, false);" & _
         "  links[i].addEventListener('touchend', function(e) { window.location = this.href; }, false);" & _
         "}" & _
         "})()"
   
    WVE.executeJavascript(WebView1, js) 'Execute the JS and CSS after the page has loaded
End Sub

Explanation:

  • CSS Injection: The CSS code snippet is designed to remove the outline and tap highlight color for links, which helps in preventing the visual indication of a link being pressed and held.
  • JavaScript Updates: Along with preventing the default context menu, the JavaScript now includes a snippet to add the CSS dynamically to the page's <head> section. It also includes prevention of the default action on touchstart for links and a manual redirection on touchend to simulate a click while suppressing the default long-press behavior.
This solution combines CSS and JavaScript to both visually and functionally suppress the default behaviors associated with tapping and holding on a link in a WebView. Be aware that overriding default browser behaviors can affect the user experience, so it's important to ensure that these changes are necessary for your application's functionality and are tested across the different devices and WebView versions your app may encounter.
 
Last edited:
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
with all due respect to chatgpt (et al.), might i humbly suggest an alternate theory: substitute "contextmenu" for "dragstart" in the original solution.

since the page appears to be yours, you can just add it to the source instead of executing javascript. why prolong the agony?
 
Upvote 0

Sandman

Expert
Licensed User
Longtime User
Thanks @JohnC (with thanks to @drgottjr acting as the thread cheer section :) ). I hadn't thought that this could be solved by adding some javascript, I thought it was one of those javaobject moments.

So, for posterity, the solution was to just add this to the end of the html page (because I control that part of the equation too):
JavaScript:
<script type="text/javascript">
    var links = document.getElementsByTagName('a');
    for(var i = 0; i < links.length; i++) {
        links[i].addEventListener('dragstart', function(event) {
            event.preventDefault();
        }, false);
    }
</script>
 
Upvote 0
Top