4, (my face ⁻̫ is red), (my face is red). Here is my face. Let’s face it.

╭ : If you look through my past articles, you’ll see that 90% of the first few greetings are the same.

Effect drawing (1.3m)

One, foreword

You can go to DEMO here. Come on **

I believe that comrades who just contacted Android soon put forward the following suggestions in the face of the product:

"In the customized WebView page, long press the popup option of the text and click select to share, forward and favorites the selected text"Copy the code

Most of the first reactions to such requirements are: this is the system behavior if the implementation needs to be implemented on the Web side.

However, the limitations of web side implementation are too great. There have been monitoring system stickboard and implementing other logic when users click copy, but this is not good user experience. Therefore, customized long-press popup menu in WebView and small controls that return selected text when clicking back to old age (^ω^)=.

2. Custom long press pop-up menu

The implementation of this step is actually very simple, first create a CustomActionWebView inherit system WebView, and then override the following two methods.

These methods are called when the user long presses to select Web text before the pop-up menu. The difference is that the first method’s menu pops up, specifying the default type. We don’t care what type of item pops up, we just intercept the ActionMode and return our own custom ActionMode.

@Override
public ActionMode startActionMode(ActionMode.Callback callback) {
    ActionMode actionMode = super.startActionMode(callback);
    return resolveActionMode(actionMode);
}

@Override
public ActionMode startActionMode(ActionMode.Callback callback, int type) 
    ActionMode actionMode =  super.startActionMode(callback, type);
    return resolveActionMode(actionMode);
}Copy the code

Here’s what we’re doing:

  • 1. Save the original actionMode object to mActionMode.
  • 2, clear the original actionMode MenuItem.
  • 3. Add our custom item to actionMode.
  • 4. Redefine click events for each menuItem.
  • 5. Get the selected text by executing JS in the click event.
  • Release the popup menu using the mActionMode saved above (otherwise memory leaks).
  • 7. Return the newly filled actionMode to the system.

/** * handle item, handle * @param actionMode */
private ActionMode resolveActionMode(ActionMode actionMode) {
    if(actionMode ! =null) {
        final Menu menu = actionMode.getMenu();
        mActionMode = actionMode;
        menu.clear();
        for (int i = 0; i < mActionList.size(); i++) {
            menu.add(mActionList.get(i));
        }
        for (int i = 0; i < menu.size(); i++) {
            MenuItem menuItem = menu.getItem(i);
            menuItem.setOnMenuItemClickListener(new Item.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem item) {
                    getSelectedData((String) item.getTitle());
                    releaseAction();
                    return true; }}); } } mActionMode = actionMode;return actionMode;
}Copy the code

Implementation effect

Get the selected text

Light custom menu, without the selected text is meaningless, so how to get the selected text? If we don’t make a turn, we will be in the south wall in the death ( ̄^ ̄)ゞ So, our great JS will appear.

First, we define a custom interface to listen for JAVASCRIPT methods, where @javascriptInterface is the key, and get the data returned by the JS side in the callback.

Then add this interface to the CustomActionWebView (usually at initialization and page load completion) and name the interface called by the JS side as “JSInterface”. (Ps: Don’t forget to start webView js.)

public void linkJSInterface() {
   addJavascriptInterface(new ActionSelectInterface(this), "JSInterface"); }.../** * the selected callback interface */
private class ActionSelectInterface {

    CustomActionWebView mContext;

    ActionSelectInterface(CustomActionWebView c) {
        mContext = c;
    }

    @JavascriptInterface
    public void callback(final String value, final String title) {
        if(mActionSelectListener ! =null) { mActionSelectListener.onClick(title, value); }}}Copy the code

Finally, when clicked, the selected text in the Web is retrieved by executing JS. In item 5 of the custom menu above, when menu is clicked, execute the js code below to call the selected item and text back to the callback in the interface above.

Familiar with JS partners have seen it:

  • You define a JS function and then execute that method in the WebView.
  • The javascript method called function getSelectedText() is defined with two variables: TXT and title.
  • Title is the name of the item passed in from the native. TXT is the selected text from the Web through the window.
  • Finally, back to the js method name we registered above, JSInterface, through its callback method, the text and name are returned to the native code callback.
  • The interface on which the JS methods are executed varies depending on the version.
/** * When clicked, get the selected text from the web page, drop back to the native JS interface * @param title passed in the clicked item text, and return it together to the native interface */
private void getSelectedData(String title) {

    String js = "(function getSelectedText() {" +
            "var txt;" +
            "var title = \"" + title + "\";" +
            "if (window.getSelection) {" +
            "txt = window.getSelection().toString();" +
            "} else if (window.document.getSelection) {" +
            "txt = window.document.getSelection().toString();" +
            "} else if (window.document.selection) {" +
            "txt = window.document.selection.createRange().text;" +
            "}" +
            "JSInterface.callback(txt,title);" +
            "}) ()";
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        evaluateJavascript("javascript:" + js, null);
    } else {
        loadUrl("javascript:"+ js); }}Copy the code

Four, the last

Now that the custom item is implemented, and clicking and selecting text returns are implemented, in callback you can happily collect, or share your selected text (◐‿◑), in one go, is it amazing?

If you are interested, download the demo and have a look. CustomActionWebView also packages remote dependencies. Welcome to use it.

Github.com/CarGuo/Cust…

Writing articles is hard work, too