Friday, February 7, 2014

Android: Overriding the default contextual action bar for text selection in WebView (Android 4.1+)

We had to create an Android app where user annotates using the text selected in an HTML page. We used the standard Webview component of Android to render the web page.

By default Android's Webview displays the standard ActionBar with Copy, Paste and other buttons when the text is selected. I wanted to either disable the Contextual Action Bar (CAB) or display a CAB with my own set of buttons. Android Webview doesn't provide ability to do either of these.

People had commented on various StackOverflow posts to either use LongPress listener or use registerContextMenu. If we setup the LongClick listener, the selection stops working and registerContextMenu doesn't work in the desired manner either.

After delving deep into the Webview code, I found out that WebViewClassic class was invoking startActionMode method of the Webview. This is all we needed. I created a new class by subclassing the Webview class and overrided the startActionMode method. After that, I just used the extended Webview instead of the default one and that was it.

The overridden method looks like this:

        public ActionMode startActionMode(ActionMode.Callback callback)
          {
                 actionModeCallback = new SelectActionModeCallback();
                return super.startActionMode(actionModeCallback);
          }



As you can note in the code above, instead of sending the ActionMode.Callback sent by Webview classic, I simply created a custom ActionMode.Callback with desired items and sent it to the subclass. This ensured that the selection worked perfectly fine and my custom CAB showed up in place of Android's default menu, each time text was selected. Works like a charm.

However, there is a small caveat in this solution. The CAB doesn't get closed by itself as the Android's default CAB and I had to write code to close it at appropriate places. Hope this helps someone.