4

I have created a custom ActionMode.Callback in order to display a custom contextual action bar for text selection in a WebView. It works beautifully in Android 4.4, but in 4.1-4.3, the selection handles are not appearing. I can still perform my custom operations on the single word that is highlighted, but the selection cannot be changed due to the missing handles.

In addition, when the ActionMode is destroyed, the selection does not clear from the screen. In contrast, if the user taps elsewhere to clear the selection, the ActionMode is not destroyed.

I'm not even sure that clearFocus() is the method I should be calling to try to remove the selection. I commented that line and the behavior in 4.4 did not change; it still worked flawlessly.

What can be done to fix these issues?


This is my current implementation:
public class CustomWebView extends WebView {

    private ActionMode.Callback mActionModeCallback;

    @Override
    public ActionMode startActionMode(Callback callback) {
        ViewParent parent = getParent();
        if (parent == null) {
            return null;
        }
        mActionModeCallback = new CustomActionModeCallback();
        return parent.startActionModeForChild(this, 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.contextual_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) {
            // This method is called when the handlebars are moved.
            loadJavascript("javascript:getSelectedTextInfo()");
            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.button_1:
                // do stuff
                break;
            case R.id.button_2:
                // do stuff
                break;

            ... // cases for other buttons

            default:
                break;
            }

            mode.finish(); // Action picked, so close the CAB
            return true;
        }

        // Called when the user exits the action mode
        @Override
        public void onDestroyActionMode(ActionMode mode) {
            // TODO This does not work in 4.3 (and probably anything older).
            clearFocus(); // Remove the selection highlight and handles.

        }
    }
}
Sean Beach
  • 2,050
  • 4
  • 26
  • 35

1 Answers1

0

I never did figure out what I was doing incorrectly that was causing this behavior. Fortunately, I did find a solution that displays the handlebars appropriately, and allows for custom actions. That solution can be found at this question: https://stackoverflow.com/a/22391169/2608235

In short, instead of creating your own ActionMode, remove the default selection actions (copy, paste, etc) and replace them with your own menu.xml layout using MenuInflater within an override of onActionModeStarted. Define an onClick for your menu elements, implement that method in your Activity, and you're done.

Community
  • 1
  • 1
Sean Beach
  • 2,050
  • 4
  • 26
  • 35