How to override default text selection of android webview os 4.1+?

I realize this is an old question, but there is not an accepted answer, and none of the provided answers have many votes.

I have achieved what you are trying to accomplish by creating a custom action mode callback. This allows the creation of a custom contextual action bar (CAB) when (in the case of a WebView) a user long-clicks the view. NOTE: This only works in 4.0+ and one piece only works in 4.4.

Create a new Android XML file containing the layout for your custom menu. Here is mine (context_menu.xml) as an example:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@+id/copy"
        android:icon="@drawable/ic_action_copy"
        android:showAsAction="always" <!-- Forces this button to be shown -->
        android:title="@string/copy">
    </item>
    <item
        android:id="@+id/button2"
        android:icon="@drawable/menu_button2icon"
        android:showAsAction="ifRoom" <!-- Show if there is room on the screen-->
        android:title="@string/button2">
    </item>
    <!-- Add as many more items as you want.
         Note that if you use "ifRoom", an overflow menu will populate
         to hold the action items that did not fit in the action bar. -->

</menu>

Now that the menu is defined, create a callback for it:

public class CustomWebView extends WebView {

    private ActionMode.Callback mActionModeCallback;

    private class CustomActionModeCallback implements ActionMode.Callback {

        // Called when the action mode is created; startActionMode() was called
        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            // Inflate a menu resource providing context menu items
            MenuInflater inflater = mode.getMenuInflater();
            inflater.inflate(R.menu.context_menu, menu);
            return true;
        }

        // Called each time the action mode is shown.
        // Always called after onCreateActionMode, but
        // may be called multiple times if the mode is invalidated.
        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            // Note: This is called every time the selection handlebars move.
            return false; // Return false if nothing is done
        }

        // Called when the user selects a contextual menu item
        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {

            switch (item.getItemId()) {
                case R.id.copy:
                // Do some stuff for this button
                   mode.finish(); // Action picked, so close the CAB
                   return true;
                case R.id.button2:
                // Do some stuff for this button
                   mode.finish();
                   return true;
                // Create a case for every item
                ...
                default:
                   mode.finish();
                   return false;
            }
        }

        // Called when the user exits the action mode
        @Override
        public void onDestroyActionMode(ActionMode mode) {
            // This will clear the selection highlight and handlebars.
            // However, it only works in 4.4; I am still investigating
            // how to reliably clear the selection in 4.3 and earlier
            clearFocus();
        }
}

Once those pieces are in place, override the startActionMode method so that the callback will actually occur on a long-click:

public class CustomWebView extends WebView {
    @Override
    public ActionMode startActionMode(Callback callback) {
        ViewParent parent = getParent();
        if (parent == null) {
        return null;
        }
        mActionModeCallback = new CustomActionModeCallback();
        return parent.startActionModeForChild(this, mActionModeCallback);
    }
}

Now you have a custom menu that will be appear and populate when a user long-clicks your WebView. For reference, I found this information from an Android Developer tutorial and modified the suggestion from this answer.

One final note: This technique overrides the native copy/paste menu for selected text. If you want to maintain that functionality, you will need to implement it yourself. (That is why my first button is ‘copy’.) If you need that, refer to this Google tutorial for more information and the proper way to implement it.

Leave a Comment