18

Similar to other browser like Chrome and Firefox, I need the user to long click a link then show a context menu but if they long click something and it is not a link then do nothing.

Using registerForContextMenu(myWebView); allows long clicking on any object which I do not want. Therefore, I think one needs to filter the objects from registerForContextMenu(myWebView); or parse the html for links which seems overkill. I have also tried overriding shouldOverrideUrlLoadingmethod:

private boolean isLongClicked = false;  

this.webView.setWebViewClient(new WebViewClient() {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
                  if(isLongCLicked){
                          //do something
                     }else
                view.loadUrl(url);

            return true;
        }

    });

    webView.setOnLongClickListener(new OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                        isLongClicked = true;
                    forumView.performClick();
                        isLongCLicked = false;
                    return false;
                }
            });

I have looked at this thread Enable longClick in WebView but it has not helped me. I tried implementing it but I get a force close.

import android.content.Context;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.webkit.WebView;

public class WebViewSub extends WebView {


    public WebViewSub(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }

    @Override
    protected void onCreateContextMenu(ContextMenu menu) {
        super.onCreateContextMenu(menu);

        HitTestResult result = getHitTestResult();

        MenuItem.OnMenuItemClickListener handler = new MenuItem.OnMenuItemClickListener() {
            public boolean onMenuItemClick(MenuItem item) {
                // do the menu action
                return true;
            }
        };

        if (result.getType() == HitTestResult.IMAGE_TYPE
                || result.getType() == HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
            // Menu options for an image.
            // set the header title to the image url
            menu.setHeaderTitle(result.getExtra());
            menu.add("save image")
                    .setOnMenuItemClickListener(handler);
            menu.add("View Image")
                    .setOnMenuItemClickListener(handler);
        } else if (result.getType() == HitTestResult.ANCHOR_TYPE
                || result.getType() == HitTestResult.SRC_ANCHOR_TYPE) {
            // Menu options for a hyperlink.
            // set the header title to the link url
            menu.setHeaderTitle(result.getExtra());
            menu.add("Save Link")
                    .setOnMenuItemClickListener(handler);
            menu.add("Share Link")
                    .setOnMenuItemClickListener(handler);
        }
    }
}

Lastly I tried using a HitTestResult, This is probably the closest I have got to solving the problem.

myWebView.setOnLongClickListener(new OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                registerForContextMenu(myWebView);
                WebView.HitTestResult result = forumView.getHitTestResult();
                if(result.getType() == 7){


                    openContextMenu(myWebView);

                }
                unregisterForContextMenu(myWebView);
                return false;
            }
        });

This does work only on links, however my context menu displays as a blank rectangle. I have tried using the actual OnLongClick View but it doesn't seem to work either. I do not think that my Context Menu is wrong; it worked outside OnLongClick.

@Override
    public void onCreateContextMenu(ContextMenu menu, View v,
            ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        getMenuInflater().inflate(R.menu.click, menu);
    }

How do I get the menu to appear correctly? I think I am on the right track using the HitTestResult onLongClick.

Edit (ANSWER):

myWebView.setOnLongClickListener(new OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                unregisterForContextMenu(myWebView);
                WebView.HitTestResult result = forumView.getHitTestResult();
                if(result.getType() == 7){
                registerForContextMenu(myWebView);


                }

                return false;
            }
        });

Every time on Long Click this unregisters the context menu then registers it, popping up the menu. I believe this works because as soon as a link is clicked it unregisters the registered context menu and then decides if it's a link to pull up the context menu. Previously, it would not give the user time to choose a option and immediately after registering the context menu unregister it.

Community
  • 1
  • 1
horvste
  • 636
  • 6
  • 19

1 Answers1

1

This is actually a situation I was coming across rather lately due to an app I have been working on -- the solution that you arrived to is essentially the same that I implemented, so here it is for completions sake:

    webView.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            unregisterForContextMenu(webView);
            WebView.HitTestResult result = webView.getHitTestResult();
            if (result.getType() == WebView.HitTestResult.SRC_ANCHOR_TYPE) {
                registerForContextMenu(webView);
            } else {
                return true;
            }

            return false;
        }

Note that by using result.getExtra() you will retrieve the filtered results from the WebView, in this case, a HTML::a tag with src=http. Note that I also ignore any other long clicks on the WebView by returning true (handled).

avluis
  • 317
  • 5
  • 18